curl sends a GET request whenever you give it only a URL: curl https://example.com/. To add parameters, put the whole URL in single quotes. Or let curl build the query with -G and --data-urlencode, which also encodes the values. Check what went out with -w '%{method} %{http_code} %{url.query}'. We ran every command on this page on 11 October 2026 with curl 8.5.0 on Ubuntu 24.04, against httpbin.org and example.com.
Most failed GET requests are not curl's fault. The shell cuts the URL at an & or refuses a ?, or curl reads braces and brackets as its own patterns. Those traps follow the basics.
How do you send a GET request with curl?
Give curl the URL. With nothing else, it sends a GET. As the everything curl guide puts it, "GET is default, using -d or -F makes it a POST, -I generates a HEAD and -T sends a PUT".
curl https://example.com/
In our run, example.com answered 200 with 577 bytes of HTML. With -v, curl showed the request line it sent, GET / HTTP/2, and three headers: Host, User-Agent: curl/8.5.0 and Accept: */*.
You do not need -X GET. The manual says that "normally you do not need this option", because it "only changes the actual word used in the HTTP request". Our request line was the same with and without it.

How do you add query parameters?
There are three ways. In our run, all three reached httpbin.org with the parameters we meant.
-
Write them into the URL, and quote the whole URL. Single quotes keep "the literal value of each character", so the shell hands the
?and the&to curl untouched.curl 'https://httpbin.org/get?country=de&limit=5' -
Let curl build the query.
-Gtakes the-ddata and "appends the provided data to the URL as a query string", instead of sending a POST.curl -G -d country=de -d limit=5 https://httpbin.org/get -
Add to an existing query with
--url-query, available since curl 7.87.0. It encodes the value, adds the&itself and keeps the method. With a-dbeside it, curl sent a POST withlimit=5in the URL andname=alicein the body.curl --url-query 'city=São Paulo' 'https://httpbin.org/get?country=br'
When do values need encoding?
-d sends its text "exactly as provided on the command line", and "curl does not convert, change or improve it". A server that reads the query as form data turns every + into a space, as the URL standard spells out. So -G -d 'q=C++' reached httpbin as C and two spaces.
--data-urlencode encodes the value first:
curl -G --data-urlencode 'q=C++' --data-urlencode 'city=São Paulo' https://httpbin.org/get
Both values arrived intact. curl 8.5.0 wrote the query as q=C%2b%2b&city=S%c3%a3o+Paulo. Lowercase and uppercase hex mean the same in a URL, and curl switched to uppercase in 8.15.0. Typed straight into the URL, a São left our 8.5.0 as raw bytes, although curl's own URL page says it encodes them. --data-urlencode avoids the question.
How do you add headers and save the answer?
-H adds a header to the request, such as an Accept header or an API key. "You may specify any number of extra headers."
curl -s -H 'Accept: application/json' -H 'X-Api-Key: KEY' 'https://httpbin.org/get?country=de'
httpbin received both headers with the query. For the answer itself, -o answer.json writes it to a file instead of the terminal: 289 bytes in our run. -s hides the progress meter, and -S still shows errors when -s is on. -i prints the response headers first, starting with the status line, HTTP/2 200 here. Our curl headers guide covers headers in depth.
How do you check what curl sent?
-w prints details after the transfer. %{method}, %{http_code} and %{url.query} show the method, the status and the encoded query:
curl -s -o /dev/null -w '%{method} %{http_code} %{url.query}\n' -G --data-urlencode 'q=C++' --data-urlencode 'city=São Paulo' https://httpbin.org/get
Our run printed GET 200 q=C%2b%2b&city=S%c3%a3o+Paulo. %{url.query} needs curl 8.1.0 or later.
By default, curl does not treat an HTTP error as a failure: a 404 ended with exit code 0. With -f, curl printed The requested URL returned error: 404 and exited with 22, which a script can catch.

Which mistakes break a GET request?
| Mistake | What happened in our run | Fix |
|---|---|---|
An unquoted & in bash | curl got only ?country=de, and limit=5 became a shell variable | Single quotes around the URL |
An unquoted ? in zsh | Not run here: zsh stops with "no matches found" | Quotes |
An & in the Windows command prompt | Not run here: the prompt treats it as a second command | Quotes, or ^& |
| JSON in braces | Two requests, each with half of the JSON, exit code 0 | -G --data-urlencode, or -g |
Brackets, as in page[size]=10 | curl: (3) bad range in URL position 30 | -g |
| A space in the URL | curl: (3) URL rejected: Malformed input to a URL function | --data-urlencode, or %20 |
-d without -G | A POST, which httpbin's /get refused with 405 | Add -G |
-X GET with -d | A GET that carried the data as a body | -G instead |
-GET | Read as -G -E T; exit code 58 over https:// | -G, or nothing |
The ampersand. In bash, a command ended by & runs "in the background", and the shell "does not wait for the command to finish". So the shell started curl with half of the URL and set limit=5 as a variable. curl's manual gives the same advice. Put the full URL in quotes "to avoid the shell from interfering with it", because of characters such as & and ?.
zsh and the command prompt. Since macOS 10.15, zsh is the default shell on a Mac. Its NOMATCH option makes it "print an error" when a pattern such as an unquoted URL with ? matches no file. bash leaves the word unchanged in that case, which is why the same command works in bash and fails in zsh. In the Windows command prompt, & is one of the special characters "that must be preceded by the escape character ^ or quotation marks".
Braces and brackets. curl reads {a,b} as a list and [1-9] as a range, so a JSON value in braces became two requests. -g (--globoff) turns that off.
A body on a GET. RFC 9110 says that content in a GET request "has no generally defined semantics". Such content also "might lead some implementations to reject the request". Use -G to put the data into the query instead.
-GET. curl joins short options, so -GET means -G plus -E T, a client certificate file named T. Over https://, our curl stopped with exit code 58, "could not load PEM client certificate from T".

What does a proxy see of your GET request?
It depends on the scheme. For an http:// address, the client sends the proxy the whole URL, query included, "in absolute-form". For https://, it sends "only the host and port" in a CONNECT request, and the query travels inside the encrypted tunnel. Our stub proxy logged GET http://httpbin.org/get?country=de&limit=5 for the first and CONNECT httpbin.org:443 for the second.
So keep secrets out of query strings where you can. RFC 9110 warns that servers and proxies "log or display the target URI in places where it might be visible to third parties". An API key in a header does not appear in a logged URI, but over plain http:// a proxy can read the headers too.
To send a GET through a proxy, add -x with the proxy URL. With our gateway's address and placeholder credentials:
curl -x http://USER:PASS@premium.hproxy.com:10000 'https://httpbin.org/get?country=de&limit=5'
We ran the same command through our stub proxy in place of the gateway. Lines from our residential proxies use this form when you need an exit address other than your own. Our guide to using proxies with curl covers the other proxy options.
What this page could not check
- We ran one curl build, 8.5.0 on Ubuntu 24.04 with bash 5.2. Newer behaviour comes from the manual and the changelog; the latest release on 11 October 2026 was 8.22.0.
- zsh and the Windows command prompt were not run. Those rows rest on the zsh manual, Apple's help page and Microsoft's documentation.
- httpbin.org decoded our queries with its own rules, such as a
+as a space, which other servers may not share. - The proxy was our stub on 127.0.0.1, which logs the request line. A real proxy may log more or less.
- Raw non-ASCII bytes in the URL left our 8.5.0 unencoded, while curl's URL page says curl encodes them. We did not test a newer build.
- One httpbin answer failed once and passed a minute later; we do not know why.
- curl releases every eight weeks, and write-out variables and encoding details change. We will run these commands again by 11 January 2027.
Sources
- curl manual, curl project, current version, read 11 October 2026: curl.se.
- everything curl: method, request method, query and convert to GET, read 11 October 2026: everything.curl.dev.
- curl documentation, URL syntax, read 11 October 2026: curl.se.
- curl changelog, releases 8.15.0, 8.21.0 and 8.22.0, read 11 October 2026: curl.se.
- RFC 9110, HTTP Semantics, sections 9.3.1 and 17.9, IETF, June 2022: rfc-editor.org.
- RFC 9112, HTTP/1.1, sections 3.2.2 and 3.2.3, IETF, June 2022: rfc-editor.org.
- RFC 3986, URI Generic Syntax, sections 2.1 and 3.4, IETF, January 2005: rfc-editor.org.
- WHATWG URL Standard, application/x-www-form-urlencoded parsing, read 11 October 2026: url.spec.whatwg.org.
- GNU Bash Reference Manual: lists of commands, single quotes and filename expansion, read 11 October 2026: gnu.org.
- zsh manual, options (NOMATCH), and Apple Support on zsh as the default shell, read 11 October 2026: zsh.sourceforge.io.
- Microsoft Learn, cmd, read 11 October 2026: learn.microsoft.com.
- Our own runs, 11 October 2026, 01:42 to 02:37 UTC, from our server: about 50 requests to httpbin.org and example.com, and a stub proxy on 127.0.0.1.



