/commands/http/show-http-response-headers
curl -I vs -i vs -v: show HTTP response headers
- tool
- HTTP
- versions
- curl 7.x – 8.x
- os
- linux, macos, windows
curl -I URL sends a HEAD request and prints only the response headers. curl -i URL sends the normal GET and prints the headers followed by the body. curl -sS -D - -o /dev/null URL prints the headers of any request (also POST) and discards the body, which is the safest choice when the server treats HEAD differently from GET.
Compare the options
A small local server (port 5035) answers every request:
cat > server.js <<'EOF'
require("http").createServer((req, res) => {
res.setHeader("Content-Type", "application/json");
res.setHeader("Cache-Control", "no-store");
res.end(JSON.stringify({ method: req.method }) + "\n");
}).listen(5035, "127.0.0.1");
setTimeout(() => process.exit(0), 5000);
EOF
node server.js &
sleep 1
hide_date() { grep -v -i '^date:'; }
echo "--- curl -I (HEAD, headers only)"
curl -sI http://127.0.0.1:5035/ | hide_date
echo "--- curl -i (GET, headers + body)"
curl -si http://127.0.0.1:5035/ | hide_date
echo "--- curl -D - -o /dev/null with POST"
curl -sS -D - -o /dev/null -X POST http://127.0.0.1:5035/ | hide_dateOutput
--- curl -I (HEAD, headers only)
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Connection: keep-alive
Keep-Alive: timeout=5
--- curl -i (GET, headers + body)
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 17
{"method":"GET"}
--- curl -D - -o /dev/null with POST
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 18The Date header is filtered out because it changes on every request. Note that the HEAD response has no body even though the server wrote one: HTTP forbids a body in responses to HEAD.
Options
| Option | Method | Shows |
|---|---|---|
| -I, --head | HEAD | Response headers only |
| -i, --include | unchanged (GET by default) | Response headers, then the body |
| -D FILE, --dump-header FILE | unchanged | Headers written to FILE (- for stdout) |
| -v, --verbose | unchanged | Request headers (>), response headers (<), connection and TLS info |
| -w "%{http_code}" | unchanged | Only selected values, such as the status code |
| -L | unchanged | Follow redirects; with -I or -i shows the headers of every hop |
Which one to use
- Quick look at a page or file:
curl -I. It downloads nothing, so it is fast even for large files, and it showsContent-Length,Last-Modified,ETagand cache headers. - Debugging an API call:
curl -iwith the same method, headers and body your application sends, so you see the exact response including the error body. - Scripts:
-D -(or-D headers.txt) with-ofor the body keeps headers and body apart, and works with any method. - Connection, TLS or redirect problems:
curl -v. Lines starting with>are what curl sent,<what it received, and*are curl's own notes (DNS, TLS handshake, certificate). The verbose output goes to stderr, so usecurl -v URL 2>&1 | grep '^<'to filter it.
Pitfalls
-Iselects theHEADmethod, so it cannot be combined with options that select another one, such as-d(which meansPOST). curl refuses before connecting:
curl -I -d 'name=demo' http://127.0.0.1:5036/ 2>&1; echo "exit status: $?"Output
Warning: You can only select one HTTP request method! You asked for both POST Warning: (-d, --data) and HEAD (-I, --head). exit status: 2
Use -i or -D - -o /dev/null with the data instead.
- Over HTTP/2 and HTTP/3, header names arrive in lower case (
content-type), and the status line readsHTTP/2 200with no reason phrase. Match header names case-insensitively (grep -i). - Without
-L, a redirect shows only the301or302response and itsLocationheader, not the final page. - In Windows PowerShell 5.1,
curlis an alias forInvoke-WebRequest, which does not accept these options. Runcurl.exeexplicitly; on Windows use-o NULwhere Unix uses-o /dev/null.
Only the status code
curl -s -o /dev/null -w '%{http_code}\n' https://www.openssl.org/FAQ
How do I see the request headers curl sends?
Use curl -v. Lines starting with > are the request line and headers curl sent; lines starting with < are the response.
How do I show only one header?
Dump the headers and filter them, for example curl -sI URL | grep -i '^content-type'. Use -D - -o /dev/null instead of -I if the server treats HEAD differently.
Can curl print the headers of every redirect?
Yes. Combine -L with -I, -i or -D -: curl prints one header block per response, from the first redirect to the final page.