Quick verdict: cURL defaults to GET — you do NOT need -X GET. Just curl URL sends a GET. Query strings go in the URL (URL-encode special chars). Add headers with -H. The single most common mistake: using -X GET with -d at the same time, which forces a GET-with-body (some servers reject this, others convert to POST silently).
The Basic GET
curl https://api.example.com/usersThat is it. No flag needed — cURL's default method is GET. The response body prints to stdout.
To see the HTTP headers too:
curl -i https://api.example.com/users # -i = include response headersJust the headers, no body:
curl -I https://api.example.com/users # -I = HEAD request (headers only)Note: -I changes the method to HEAD, not GET. For a GET that only shows headers, combine -i with -o /dev/null for the body and --silent to hide progress.
Query Strings
Append params directly to the URL:
curl "https://api.example.com/search?q=hello&page=1&sort=date"Always quote URLs with ? or & — bash interprets & as "run in background." Single or double quotes both work; double if you need shell variable expansion.
For dynamic values with special chars, use --data-urlencode with -G:
curl -G https://api.example.com/search \
--data-urlencode "q=hello world & more" \
--data-urlencode "page=1"-G tells cURL "use -d data as query string instead of POST body." cURL URL-encodes each value safely.
Custom Headers
curl https://api.example.com/users \
-H "Accept: application/json" \
-H "Authorization: Bearer eyJhbGc..." \
-H "User-Agent: MyApp/1.0"Multiple -H flags add multiple headers. To remove a default header, send it empty:
curl -H "User-Agent:" https://api.example.com/users # removes UACommon GET headers worth knowing:
Accept: application/json— ask for JSONAccept-Language: en-US,en;q=0.9— language preference (some sites return different content per language)Accept-Encoding: gzip, deflate, br— compress (use--compressedshortcut)If-None-Match: "etag-value"— conditional GET; server returns 304 if unchanged
Cookies
Send a cookie:
curl -b "session=abc123" https://example.com/dashboardRead cookies from / write cookies to a Netscape-format cookie jar:
# Save cookies to a file (after login GET that sets cookies)
curl -c cookies.txt https://example.com/login-step1
# Reuse those cookies on a subsequent request
curl -b cookies.txt https://example.com/protected-pageFor complex flows (login + scrape), the cookie jar handles session continuity across multiple GET calls.
Follow Redirects
By default cURL does NOT follow redirects — it shows the 301/302 response and stops. Add -L:
curl -L https://example.com/short-urlSee cURL follow redirects for the full details on max redirects, redirect-method behavior, and security gotchas.
GET JSON Responses
Pipe to jq for pretty-printing and querying:
curl -s -H "Accept: application/json" https://api.github.com/users/torvalds | jq .
# Just the public_repos field
curl -s -H "Accept: application/json" https://api.github.com/users/torvalds | jq .public_repos-s (silent) hides the progress meter so jq parses cleanly. Combine with -S (-sS) to still show errors.
GET Through a Proxy
curl --proxy http://USER:PASS@gw.spyderproxy.com:8000 \
https://api.example.com/dataFor geo-locked APIs or rate-limited endpoints, route GETs through residential proxies. The --proxy flag works for HTTPS targets too — cURL CONNECTs through the proxy to reach the target.
Multiple GETs with rotating IPs:
for i in {1..10}; do
SID=$((RANDOM))
curl --proxy "http://USER-session-$SID:PASS@gw.spyderproxy.com:8000" \
https://target.com/page/$i
doneEach iteration uses a different sticky-session IP via the session-N token.
Output Timing and Stats
curl -s -o /dev/null \
-w "HTTP %{http_code}\nDNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nTotal: %{time_total}s\n" \
https://api.example.comUseful for measuring real-world latency from your network. The %{var} tokens are listed in man curl under --write-out.
Common GET Errors
- "curl: (3) URL using bad/illegal format" — missing quotes around URL with special chars. Wrap in quotes.
- "curl: (6) Could not resolve host" — DNS failure. Check the hostname, your network, or use
--resolveto bypass DNS. - "curl: (7) Failed to connect" — host refused the connection. Firewall, wrong port, or service down.
- "curl: (28) Operation timed out" — see cURL timeout fixes.
- HTML returned instead of JSON — you got a Cloudflare challenge or a 403 page. Add a real User-Agent and route through a residential proxy.
When NOT to Use GET
RFC 7231 says GETs should be safe (no state changes) and idempotent (same result every time). Do not use GET for:
- Form submissions that create/modify data — use POST
- File uploads — use POST with multipart (see cURL POST guide)
- Anything with secrets in the URL — query strings leak to logs, browser history, and referer headers
Related: cURL POST, cURL basic auth, cURL timeout, Mastering cURL.