// curl
curl Cheatsheet
The flags you reach for in real debugging — JSON POSTs, auth, redirects, TLS pinning, timing and CI-safe error handling.
Updated
Most-used recipes
JSON POST
curl --json '{"name":"alice"}' https://api.example.com/usersHeaders + bearer token
curl -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" https://api.example.com/me
Inspect just the response status + timing
curl -o /dev/null -s -w "code=%{http_code} dns=%{time_namelookup}s tcp=%{time_connect}s ttfb=%{time_starttransfer}s total=%{time_total}s\n" https://example.comTest a host before flipping DNS
curl --resolve example.com:443:198.51.100.10 https://example.com -I
CI-safe (fail on HTTP errors, quiet otherwise)
curl -fsSL https://example.com/release.tar.gz -o release.tar.gz
Multipart upload
curl -F "file=@./image.png" -F "caption=hello" https://api.example.com/upload
Flag reference
| Short | Long | Purpose |
|---|---|---|
| -X | --request | HTTP method (GET, POST, PUT, DELETE, PATCH). |
| -H | --header | Add a request header. Repeat for multiple. |
| -d | --data | POST body (URL-encoded). Forces method to POST. |
| --data-raw | — | Like -d but no @file or special-char processing. |
| --data-binary | — | Send body exactly as-is. Use for JSON/binary. |
| --json | — | Shortcut: sets Content-Type + Accept to application/json. |
| -F | --form | Multipart form field. Use @file to upload. |
| -u | --user | Basic auth user:password. |
| -b | --cookie | Send cookies (string or file). |
| -c | --cookie-jar | Save cookies to file. |
| -L | --location | Follow redirects. |
| -I | --head | Send HEAD — fetch headers only. |
| -i | --include | Include response headers in output. |
| -v | --verbose | Show request/response detail. Use -vv for more. |
| --trace | — | Full hex trace to file. --trace-ascii for readable. |
| -o | --output | Write body to file. |
| -O | --remote-name | Save with the URL's filename. |
| -s | --silent | Suppress progress meter. Use with -S to keep errors. |
| -f | --fail | Exit non-zero on HTTP ≥ 400. Critical for scripts. |
| -k | --insecure | Skip TLS verification. Debug only — never in prod. |
| --cacert | — | Use a custom CA bundle. |
| --resolve | — | Force host:port → IP. Test before DNS cutover. |
| -x | --proxy | Route through proxy (http://user:pass@host:port). |
| --max-time | — | Total operation timeout in seconds. |
| --connect-timeout | — | TCP connect timeout in seconds. |
| --retry | — | Retry on transient errors. Pair with --retry-delay. |
| -w | --write-out | Format string for stats: %{http_code}, %{time_total}. |
| -G | --get | Convert -d data into a GET query string. |
| --http2 | — | Force HTTP/2. --http3 for QUIC. |
FAQ
- How do I send a JSON POST with curl?
- Use --json to set Content-Type and Accept automatically: curl --json '{"name":"x"}' https://api.example.com/users. On older curl, use -H 'Content-Type: application/json' --data-raw '{...}'.
- How do I see why curl is hanging?
- Add -v for verbose output, or --trace-ascii trace.txt for the full request/response. Combine with --connect-timeout to fail fast.
- How do I test a site before changing DNS?
- Use --resolve: curl --resolve example.com:443:198.51.100.10 https://example.com. This skips DNS and forces curl to use your target IP.
- Why does curl exit 0 even on a 500 response?
- By default curl only fails on transport errors. Add -f (--fail) so HTTP 4xx/5xx return non-zero. For scripting, also use -sS to keep errors but hide the progress bar.