The cURL Cheatsheet — 15 Flags That Do Everything
One screen, print it or pin it. Grouped by job, not alphabetically, because man curl sorted 270 options by name and you already know how that went. Deeper reasoning behind these choices lives in the flags that matter; this is the recall version. Paste any of it back into the converter if you want the equivalent in your language.
Request shape
-H 'Key: value'— headers, repeatable. With-d, curl defaults toapplication/x-www-form-urlencoded; send JSON without-H 'Content-Type: application/json'and the API reads a form POST.-d 'a=1&b=2'— body; implies POST. Raw text, no encoding, leading@reads a file.--data-raw '@v=1'— body byte-for-byte, no@or newline interpretation.-G -d 'a=1'— GET with the data appended as a query string. The legitimate way to "GET with params" from the shell.--url-query 'a=1'— add a query pair without touching the method (curl 7.87.0+). See query hacks.-F [email protected]— multipart upload; never use-dfor files.
Transport
--compressed— negotiate gzip/br/zstd. Without it you may be timing an uncompressed 4 MB body.-L— follow redirects. Without it a 301 returns the redirect page and your parser eats it happily.--connect-timeout 5 --max-time 30— both, in every CI script. A default connect hang is 120s+ (TCP, not curl).-k— skip TLS verification: lab only. The production fix is--cacert bundle.pem.--retry 2 --retry-delay 1— retry transient failures; curl only retries what the spec says is safe.
Output
-o out.bin/-O— write to file instead of stdout;-Okeeps the remote filename.-i— status line and response headers before the body. The cure for "it worked in curl."-sS— silent progress meter, loud errors.-salone hides the error, which is the interesting part.-w '%{http_code} %{time_total}\n'— templated summary; pair with-o /dev/nullfor a poor man's ping.--fail-with-body— non-zero exit on 4xx/5xx and keep the body.-fthrows the error body away.
Auth
-u 'user:pass'— Basic by default; curl picks the strongest scheme the server offers for other auth types.-H 'Authorization: Bearer <tok>'— tokens go in a header, not a query param that lands in access logs.-b jar.txt/-c jar.txt— read/write a cookie jar;-bwith a literal string sends that cookie directly.
Debug
-v— handshake, ALPN, request and response headers.2>&1if your pipe eats stderr.--trace-ascii trace.log— full protocol trace without the hex column.-w '%{http_version} %{url_effective}\n'— which HTTP version and which URL you actually landed on after redirects.
Status codes worth memorizing
| Code | Means | What to check |
|---|---|---|
| 200 / 204 | OK / no body | 204 has no body — your JSON parse failing is correct behavior |
| 301 vs 307/308 | Permanent redirect | 307/308 preserve method and body; 301 may not |
| 304 | Not Modified | Your If-None-Match worked; stop calling it a failure |
| 400 | Bad request | Usually your body or Content-Type, not the server |
| 401 vs 403 | No credentials vs wrong credentials/forbidden | 401: header missing. 403: header present, answer wrong |
| 405 | Method not allowed | Check the Allow header; your -X is wrong |
| 408 / 504 | Request/server timeout | Slow body upload vs dead upstream |
| 413 / 415 | Too large / bad media type | Body size vs Content-Type — two different mistakes |
| 429 | Rate limited | Honor Retry-After; --retry does since 7.66.0 — but only if you set --retry at all |
| 502 / 503 | Bad gateway / unavailable | Proxy/gateway is down or shedding load; 503 often wants Retry-After too |
Decoding "Copy as cURL"
DevTools emits flags you didn't choose. What they mean and whether to keep them:
--compressed— addsAccept-Encoding. Keep it; real clients send it.--http2— Chrome's hint that the page negotiated HTTP/2. Harmless ifcurl --versionshowsHTTP2; drop it otherwise.-H 'sec-fetch-mode: cors'and friends (sec-ch-ua,sec-ch-ua-platform) — browser-internal client hints. Drop them; some WAFs reject replayedsec-*sets.-H 'cookie: ...'or-b '...'— your live session cookies. Replay sends them; scrub before committing to a script or a ticket.--data-raw/--data-ascii/--data-binary— the body, spelled differently by browser and version.--data-rawis the safest to keep; the others interpret@/newlines differently.-X POSTwith a body — redundant; the body already implies POST.-X GET— actively useless; remove it. Some caches stop caching when the method is stated explicitly.-H 'origin: ...'/-H 'referer: ...'— keep while testing an authenticated API (CSRF checks read them); drop before it becomes a shared snippet.
FAQ
What's the smallest command that's actually production-safe? curl -sS --fail-with-body --connect-timeout 5 --max-time 30 -o /dev/null URL — silent, fails loudly on HTTP errors, bounded in time, no stray output.
When do I need -X at all? Only for methods with no body and no shortcut: -X DELETE, -X PATCH, -X HEAD (vs -I). For GET/POST, curl already infers correctly and -X only adds risk.
Where do I put the timeout in a proxy environment? -x proxy:port plus the same --connect-timeout/--max-time. Note that HTTP/3 cannot traverse a proxy at all — see HTTP/3 status.