curl Cheatsheet
Headers and Methods
Use this curl reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Setting the method
-X / --request overrides the method curl would otherwise pick. It only
changes the verb, it never adds a body, so -X POST on its own sends a POST with
Content-Length: 0.
curl -X DELETE https://api.example.com/users/42 curl -X PUT -d '{}' -H 'Content-Type: application/json' https://ex.com/v1/a curl -X POST https://api.example.com/ping # empty POST body
Most of the time you do not need -X. The body flags already imply the method,
and forcing the verb is what breaks redirect following.
| You pass | curl sends |
|---|---|
| nothing | GET |
-d, --data-raw, --data-binary, --data-urlencode | POST |
--json | POST |
-F / --form | POST (multipart) |
-T / --upload-file | PUT (HTTP) |
-I / --head | HEAD |
-G / --get | GET, data moved to the query string |
Combining
-X POSTwith-Lkeeps POST on every hop, because-Xis sticky. Without-X, curl correctly downgrades a 301/302/303 redirect to GET. If you want the method preserved deliberately, that is--post301,--post302, and--post303.
Request headers
-H / --header is repeatable and takes a full Name: value string. curl sets
Host, User-Agent, and Accept: */* by default, and any -H with the same
name replaces the default rather than adding a second copy.
curl -H 'Accept: application/json' \ -H 'X-Request-Id: 7f3a' \ -H 'Authorization: Bearer eyJhbGci...' \ https://api.example.com/me
| Form | Effect |
|---|---|
-H 'Name: value' | Set or replace the header |
-H 'Name;' | Send Name with an empty value |
-H 'Name:' | Remove an internal header curl would send |
-H @headerfile | Read one header per line from a file |
-A 'ua' | Shorthand for User-Agent |
-e 'url' | Shorthand for Referer |
--proxy-header | Header for the proxy only, not the origin |
curl -H 'Accept:' https://ex.com/ # drop the default Accept curl -H 'Host: internal.svc' https://10.0.0.4/health
Header casing and duplicates
HTTP/1.1 header names are case insensitive, but HTTP/2 and HTTP/3 require
lowercase on the wire. curl lowercases for you on those versions, so the casing
you type only matters for readability. Duplicate -H entries with the same
name are both sent, which servers often reject, so prefer one line per header.
curl -v --http1.1 -H 'X-A: 1' -H 'X-A: 2' https://ex.com/ 2>&1 | grep '^> X-A'
Reading response headers
| Flag | Behavior |
|---|---|
-i / --include | Response headers then the body, on stdout |
-I / --head | HEAD request, headers only |
-D <f> / --dump-header <f> | Write headers to a file, - means stdout |
-v / --verbose | Request and response headers on stderr |
-w '%header{name}' | Print one response header value |
curl -sI https://example.com | grep -i '^content-type' curl -s -D - -o /dev/null https://example.com curl -so /dev/null -w '%header{content-type}\n' https://example.com
%header{...} needs curl 7.84.0 or newer and is the clean way to pull a single
value without piping through grep.
Conditional and range requests
Cheap ways to ask for less than the whole body, useful against big files and CDN-cached assets.
curl -r 0-1023 -o head.bin https://ex.com/big.iso # first 1 KiB curl -r -500 -o tail.bin https://ex.com/big.iso # last 500 bytes curl -z 'Tue, 01 Apr 2025 00:00:00 GMT' -O https://ex.com/f.txt curl -z file.txt -O https://ex.com/file.txt # if newer than local curl --etag-save et.txt -O https://ex.com/f.json # store the ETag curl --etag-compare et.txt -O https://ex.com/f.json # send If-None-Match
-r / --range sends Range, and -z / --time-cond sends
If-Modified-Since. A server that ignores Range answers 200 with the whole
body instead of 206, so check the status before trusting the size.
HTTP version selection
curl negotiates the highest version both sides support. Pin it when you are isolating a protocol bug.
| Flag | Meaning |
|---|---|
--http1.1 | Force HTTP/1.1 |
--http2 | ALPN upgrade to HTTP/2 over TLS |
--http2-prior-knowledge | HTTP/2 over cleartext, no upgrade dance |
--http3 | HTTP/3 over QUIC |
--http3-only | HTTP/3 with no fallback |
--no-alpn | Disable ALPN, forcing HTTP/1.1 in practice |
curl -sI --http1.1 https://example.com | head -1 curl -so /dev/null -w '%{http_version}\n' https://example.com
--http3 requires a build with an HTTP/3 backend. Check curl -V for HTTP3
in the feature line first, since a curl without it fails the option rather than
falling back.