Skip to content

Type an option name like full_page, an error code, or a topic.

Fix curl: (3) URL using bad/illegal format

Why curl stops with error 3, URL using bad/illegal format or missing URL, and how to fix each cause in bash, zsh, cmd and PowerShell.

curl: (3) URL using bad/illegal format or missing URL means curl could not read the address you gave it as a URL. Almost always the shell or a copy-paste changed it on the way: a space, a smart quote, an unescaped &, a stray line break. Put the whole URL in double quotes, encode spaces as %20, and pass a URL that sits inside another URL with --data-urlencode:

Request
curl -G "https://curlshot.com/api/v1/screenshot" \
  -H "X-Access-Key: YOUR_ACCESS_KEY" \
  --data-urlencode "url=https://shop.example/item?id=7&color=red" \
  -d "format=png" \
  --output item.png

curl encodes the page address for you, so the API receives one url option with id=7&color=red kept inside it, and you get item.png.

Recent curl versions name the reason after URL rejected:. Older versions, and many programs built on libcurl, print only the general text for error 3, URL using bad/illegal format or missing URL. It is the same error, and the same fixes apply.

curl saysUsual causeFix
URL rejected: Malformed input to a URL functionA space, a tab or a line-break character in the URLStep 1
URL rejected: Port number was not a decimal number between 0 and 65535Smart quotes, or single quotes in Windows cmd, became part of the URLStep 4, step 6
URL rejected: Bad hostnameA \ line break in Windows cmd or PowerShell was passed to curl as a URLStep 5
unmatched brace in URL position N or bad range in URL position N{ } or [ ] in the URL, which curl reads as a patternStep 7
URL rejected: No host part in the URLThe URL has no host, e.g. https:// alone or an empty variable before the pathStep 8

Every command on this page was run with curl 8.7 in bash, zsh and PowerShell 7.

#1. Remove spaces, tabs and line breaks

A URL cannot contain a space, even inside quotes. curl refuses it:

Fails
curl "https://example.com/my page"
# curl: (3) URL rejected: Malformed input to a URL function

Write the space as %20:

Works
curl "https://example.com/my%20page"

A tab, or a carriage return (\r) at the end of a line read from a file saved on Windows, fails in the same way. Remove the \r before you use the value:

Works
curl "$(tr -d '\r' < url.txt)"

#2. Put the URL in double quotes

&, ?, * and # mean something to the shell. Without quotes, the shell acts on them before curl starts:

Fails
curl https://curlshot.com/api/v1/screenshot?access_key=YOUR_ACCESS_KEY&url=https://example.com
  • In bash, & sends the command to the background and cuts the URL there. curl only gets ...?access_key=YOUR_ACCESS_KEY, and the shell reads url=https://example.com as a separate command, so the page address is lost.
  • In zsh, ? is a wildcard, so the command stops before curl runs with zsh: no matches found.

Quote the whole URL, from the first character to the last:

Works
curl "https://curlshot.com/api/v1/screenshot?access_key=YOUR_ACCESS_KEY&url=https://example.com" \
  --output example.png

#3. Encode a URL that sits inside another URL

A screenshot API takes the page to capture as a parameter, so one URL travels inside another. If the inner URL has its own ?, & or #, those characters split the outer one:

Fails
curl "https://curlshot.com/api/v1/screenshot?access_key=YOUR_ACCESS_KEY&url=https://shop.example/item?id=7&color=red"

curl does not complain here, but the API receives url=https://shop.example/item?id=7 and a separate color=red. CurlShot refuses the unknown color option with invalid_options. A # is worse: it ends the URL, and everything after it is never sent.

Let curl encode the inner URL. -G puts the data in the query string of a GET request, and --data-urlencode encodes the value after url=:

Works
curl -G "https://curlshot.com/api/v1/screenshot" \
  -H "X-Access-Key: YOUR_ACCESS_KEY" \
  --data-urlencode "url=https://example.com/docs?lang=en#install" \
  -d "full_page=true" \
  --output docs.png

The API receives url=https%3a%2f%2fexample.com%2fdocs%3flang%3den%23install, which it decodes back to the full address. The same pattern is used in the cURL examples.

#4. Replace smart quotes and hidden characters

Chat apps, word processors and some web pages turn " into curly quotes, “ and ”. The shell does not treat them as quotes, so they become part of the URL:

Fails
curl “https://example.com”
# curl: (3) URL rejected: Port number was not a decimal number between 0 and 65535

Retype the quotes as plain ". To see characters you cannot see on screen, print the value with printf %q. This is the output in bash; zsh shows the same characters in a slightly different form:

Check
printf '%q\n' "$URL"
# $'\342\200\234https://example.com\342\200\235'   <- smart quotes
# $'https://example.com/a\r'                     <- a carriage return

#5. Check how a long command is split over lines

Each shell has its own line-continuation character, and it must be the very last character on the line:

ShellContinue a line with
bash, zsh\
Windows cmd^
PowerShell` (backtick)

A space after \ in bash or zsh breaks the command in two, and curl gets a lone space as a URL: URL rejected: Malformed input to a URL function. A \ used in cmd or PowerShell is passed to curl as a URL of its own: URL rejected: Bad hostname.

This is the request from the top of the page in PowerShell:

PowerShell
curl.exe -G "https://curlshot.com/api/v1/screenshot" `
  -H "X-Access-Key: YOUR_ACCESS_KEY" `
  --data-urlencode "url=https://shop.example/item?id=7&color=red" `
  -d "format=png" `
  --output item.png

And in cmd:

Windows cmd
curl -G "https://curlshot.com/api/v1/screenshot" ^
  -H "X-Access-Key: YOUR_ACCESS_KEY" ^
  --data-urlencode "url=https://shop.example/item?id=7&color=red" ^
  -d "format=png" ^
  --output item.png

When in doubt, put the whole command on one line.

#6. Use double quotes on Windows

cmd only knows double quotes. Single quotes are passed on to curl as part of the URL, which then starts with 'https:

Windows cmd: fails
curl 'https://example.com'
Windows cmd: works
curl "https://example.com"

In cmd, & outside double quotes also starts a new command. In a .bat file, write each % of an encoded URL twice (%%20), or cmd reads it as a variable.

In Windows PowerShell 5.1, curl is an alias of Invoke-WebRequest, not curl, so curl options fail with a PowerShell error. Type curl.exe instead. PowerShell 7 and later have no such alias. In PowerShell, single and double quotes both work, and & outside quotes is an error or a background job, so quote the URL there too.

#7. Turn off globbing for braces and brackets

curl reads {a,b} and [1-5] in a URL as patterns and fetches every match. An unclosed or unexpected one stops it:

Fails
curl "https://example.com/search?filter={a"
# curl: (3) unmatched brace in URL position 35:

Add -g (--globoff) to send the characters as they are:

Works
curl -g "https://example.com/search?filter={a"

Or encode them: { is %7B, } is %7D, [ is %5B and ] is %5D. With --data-urlencode, as in step 3, the brackets are encoded for you.

#8. Check the scheme and the host

A URL with a scheme but no host fails:

Fails
curl "https://"
# curl: (3) URL rejected: No host part in the URL

This often comes from a variable that is empty, for example curl "https://$HOST/path" when $HOST was never set. Print the variable before the call. When the whole URL is an empty variable, curl "$URL", recent curl versions stop with option : blank argument where content is expected instead.

curl itself accepts example.com without https:// and guesses the scheme. The url option of the CurlShot API does not: it needs a full address that starts with http:// or https://, or the request fails with invalid_options.

#Questions

#What does curl error 3 mean?

Error 3 is CURLE_URL_MALFORMAT: the URL was not properly formatted, so curl stopped before it connected to anything. Nothing was sent, so a server or an API cannot be the cause.

#Why does the URL work in my browser but not in curl?

The browser fixes the address for you: it encodes spaces and other characters before it sends the request. curl sends the URL exactly as it gets it, and the shell may have changed it before curl even started.

#Should I use single or double quotes?

In bash, zsh and PowerShell, either works. Single quotes stop the shell from expanding $VARIABLES, double quotes allow it. In Windows cmd, use double quotes only.

#How do I pass a URL with & as a query parameter?

Use -G with --data-urlencode "url=...", as in step 3. curl encodes the &, ? and # of the inner URL, so the server receives it as one value.

#Does -g change my request?

Only how curl reads the URL you typed: { } and [ ] are sent as they are instead of being expanded into several requests. Use it whenever a URL has those characters and you want one request.

#Next steps

  • Copy a working request from the cURL examples.
  • Get an access key and take a first screenshot in Getting started.
  • If the request reaches the API and fails there, the answer is a JSON message. Errors lists every code with its fix.
  • No account yet? Create one for free.