Command line curl can display response header by using -D
option, but I want to see what request header it is sending. How can I do that?
-
37`curl --head http://google.com` will do the same as the `-I` flag :) – Abel Terefe May 13 '13 at 11:11
-
15Note on using `--head`/`-I`: not all servers respond exactly the same to `HEAD` requests (for example, `Content-Encoding` would be missing if you were attempting to verify that the body would be gzipped) and not all servers support `HEAD`. `-v` is usually the safer choice. – cfeduke Feb 07 '14 at 15:39
-
4possible duplicate of [How can I see the request headers made by curl when sending a request to the server?](http://stackoverflow.com/questions/866946/how-can-i-see-the-request-headers-made-by-curl-when-sending-a-request-to-the-ser) – Jeremy Logan Mar 28 '14 at 15:16
-
I didn't get it since any modification in order to fulfill OP's request (pun wasn't intended) requires changes on the command (i.e. `curl` and its arguments) and since command sets the request headers you already see those. AFAIK the request is all in or nothing, so either all the headers will be sent, or none. Am I missing something? – ozanmuyes May 31 '23 at 10:43
9 Answers
curl's -v
or --verbose
option shows the HTTP request headers, among other things. Here is some sample output:
$ curl -v http://google.com/
* About to connect() to google.com port 80 (#0)
* Trying 66.102.7.104... connected
* Connected to google.com (66.102.7.104) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.16.4 (i386-apple-darwin9.0) libcurl/7.16.4 OpenSSL/0.9.7l zlib/1.2.3
> Host: google.com
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.com/
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 15 Jul 2010 06:06:52 GMT
< Expires: Sat, 14 Aug 2010 06:06:52 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 219
< X-XSS-Protection: 1; mode=block
<
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
* Connection #0 to host google.com left intact
* Closing connection #0

- 159,146
- 25
- 197
- 199
-
9What if I just want to construct the package but don't want to send it? – PuercoPop Jul 19 '13 at 16:56
-
@jacobsimeon I thinks that's because it shows not only the **Request headers** but also the **Response headers** and **Response body**. – Peyman Mohamadpour Jun 09 '16 at 14:07
A popular answer for displaying response headers, but OP asked about request headers.
curl -s -D - -o /dev/null http://example.com
-s
: Avoid showing progress bar-D -
: Dump headers to a file, but-
sends it to stdout-o /dev/null
: Ignore response body
This is better than -I
as it doesn't send a HEAD
request, which can produce different results.
It's better than -v
because you don't need so many hacks to un-verbose it.

- 392
- 2
- 14

- 13,895
- 4
- 51
- 54
-
32Read the question - this is for response headers not request headers – Graeme Stuart Nov 04 '14 at 14:12
-
`-o` option is what I was looking for (however question is asking something else) – Timofey Apr 06 '15 at 09:40
-
114
-
3This command is a bit different for Windows: `curl -sD - -o NULL http://example.com` – Sergey V. Aug 26 '16 at 17:30
-
4@SergeyVlasov Actually, the equivalent of `/dev/null` in Windows is `nul`, not `null`. – Francisco Zarabozo Dec 11 '17 at 07:37
-
11Even though this question asks for request headers, google is directing everybody here who is looking for response headers so we are all glad this answer is here. And this answer is the best for getting response headers. Thanks!!! – biomiker Mar 26 '19 at 15:55
-
1
-
1Sending the headers to stderr with `-D /dev/stderr` (instead of `-D-`) enables continuing the pipeline into other things like `| jq`. – Micah Elliott Aug 02 '22 at 18:17
I believe the command line switch you are looking for to pass to curl is -I
.
Example usage:
$ curl -I http://heatmiser.counterhack.com/zone-5-15614E3A-CEA7-4A28-A85A-D688CC418287
HTTP/1.1 301 Moved Permanently
Date: Sat, 29 Dec 2012 15:22:05 GMT
Server: Apache
Location: http://heatmiser.counterhack.com/zone-5-15614E3A-CEA7-4A28-A85A-D688CC418287/
Content-Type: text/html; charset=iso-8859-1
Additionally, if you encounter a response HTTP status code of 301, you might like to also pass a -L
argument switch to tell curl
to follow URL redirects, and, in this case, print the headers of all pages (including the URL redirects), illustrated below:
$ curl -I -L http://heatmiser.counterhack.com/zone-5-15614E3A-CEA7-4A28-A85A-D688CC418287
HTTP/1.1 301 Moved Permanently
Date: Sat, 29 Dec 2012 15:22:13 GMT
Server: Apache
Location: http://heatmiser.counterhack.com/zone-5-15614E3A-CEA7-4A28-A85A-D688CC418287/
Content-Type: text/html; charset=iso-8859-1
HTTP/1.1 302 Found
Date: Sat, 29 Dec 2012 15:22:13 GMT
Server: Apache
Set-Cookie: UID=b8c37e33defde51cf91e1e03e51657da
Location: noaccess.php
Content-Type: text/html
HTTP/1.1 200 OK
Date: Sat, 29 Dec 2012 15:22:13 GMT
Server: Apache
Content-Type: text/html
-
52The `-I` option shows the *response* headers. The question was about the *request* headers. – Asaph Jan 05 '13 at 14:54
-
68The `-I` options causes curl to do an `HTTP HEAD`, which could change the response from the server. Better to use `-v` switch I believe. – acw Apr 17 '13 at 09:10
-
1If you try this with anything else than a `HEAD` request (like `-X POST`) and get **"You can only select one HTTP request!"** than http://stackoverflow.com/questions/286982/curl-post-data-and-headers-only will probably help you out. The thing is that `-I` does a `HEAD` request, like `acw` stated and when your `curl` call set up to do another call you have two HTTP requests in `curl` call... – flu May 15 '14 at 09:54
-
9This is a very wrong answer. (I promise I'm usually very kind on here.) 1. It does the opposite of what the OP asks. 2. It uses a request method of `HEAD` instead of `GET` or `POST`. 3. It should NEVER be used to "just see the headers" unless you are trying to see how your server responds differently to a `HEAD` as opposed to a `GET`. It will be the same most of the time, but not always. To see only the headers use `curl -o /dev/null -D /dev/stdout`. That will give the expected results 100% of the time. – Bruno Bronosky Apr 14 '16 at 22:29
-
2Probably worth mentioning that `-i` prints both the response headers and body. – Kris Dover Jul 16 '20 at 01:24
The verbose option is handy, but if you want to see everything that curl does (including the HTTP body that is transmitted, and not just the headers), I suggest using one of the below options:
--trace-ascii -
# stdout--trace-ascii output_file.txt
# file

- 12,272
- 10
- 61
- 91

- 16,089
- 7
- 81
- 124
-
I dont think so as it shows the response headers & body too! – Peyman Mohamadpour Jun 09 '16 at 14:14
You get a nice header output with the following command:
curl -L -v -s -o /dev/null google.de
-L, --location
follow redirects-v, --verbose
more output, indicates the direction-s, --silent
don't show a progress bar-o, --output /dev/null
don't show received body
Or the shorter version:
curl -Lvso /dev/null google.de
Results in:
* Rebuilt URL to: google.de/
* Trying 2a00:1450:4008:802::2003...
* Connected to google.de (2a00:1450:4008:802::2003) port 80 (#0)
> GET / HTTP/1.1
> Host: google.de
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.de/
< Content-Type: text/html; charset=UTF-8
< Date: Fri, 12 Aug 2016 15:45:36 GMT
< Expires: Sun, 11 Sep 2016 15:45:36 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 218
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
<
* Ignoring the response-body
{ [218 bytes data]
* Connection #0 to host google.de left intact
* Issue another request to this URL: 'http://www.google.de/'
* Trying 2a00:1450:4008:800::2003...
* Connected to www.google.de (2a00:1450:4008:800::2003) port 80 (#1)
> GET / HTTP/1.1
> Host: www.google.de
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 12 Aug 2016 15:45:36 GMT
< Expires: -1
< Cache-Control: private, max-age=0
< Content-Type: text/html; charset=ISO-8859-1
< P3P: CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."
< Server: gws
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
< Set-Cookie: NID=84=Z0WT_INFoDbf_0FIe_uHqzL9mf3DMSQs0mHyTEDAQOGY2sOrQaKVgN2domEw8frXvo4I3x3QVLqCH340HME3t1-6gNu8R-ArecuaneSURXNxSXYMhW2kBIE8Duty-_w7; expires=Sat, 11-Feb-2017 15:45:36 GMT; path=/; domain=.google.de; HttpOnly
< Accept-Ranges: none
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
<
{ [11080 bytes data]
* Connection #1 to host www.google.de left intact
As you can see curl
outputs both the outgoing and the incoming headers and skips the bodydata althought telling you how big the body is.
Additionally for every line the direction is indicated so that it is easy to read. I found it particular useful to trace down long chains of redirects.

- 962
- 10
- 12
-
6I like this better than `-v` option with higher votes. Also, just for brevity this can also be `curl -Lvso /dev/null
` as long as the `o` comes at the end. – shriek Jun 15 '17 at 13:30
A command like the one below will show three sections: request headers, response headers and data (separated by CRLF). It avoids technical information and syntactical noise added by curl.
curl -vs www.stackoverflow.com 2>&1 | sed '/^* /d; /bytes data]$/d; s/> //; s/< //'
The command will produce the following output:
GET / HTTP/1.1
Host: www.stackoverflow.com
User-Agent: curl/7.54.0
Accept: */*
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Location: https://stackoverflow.com/
Content-Length: 149
Accept-Ranges: bytes
Date: Wed, 16 Jan 2019 20:28:56 GMT
Via: 1.1 varnish
Connection: keep-alive
X-Served-By: cache-bma1622-BMA
X-Cache: MISS
X-Cache-Hits: 0
X-Timer: S1547670537.588756,VS0,VE105
Vary: Fastly-SSL
X-DNS-Prefetch-Control: off
Set-Cookie: prov=e4b211f7-ae13-dad3-9720-167742a5dff8; domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly
<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found <a HREF="https://stackoverflow.com/">here</a></body>
Description:
-vs
- add headers (-v) but remove progress bar (-s)2>&1
- combine stdout and stderr into single stdoutsed
- edit response produced by curl using the commands below/^* /d
- remove lines starting with '* ' (technical info)/bytes data]$/d
- remove lines ending with 'bytes data]' (technical info)s/> //
- remove '> ' prefixs/< //
- remove '< ' prefix

- 947
- 7
- 15
I had to overcome this problem myself, when debugging web applications. -v
is great, but a little too verbose for my tastes. This is the (bash-only) solution I came up with:
curl -v http://example.com/ 2> >(sed '/^*/d')
This works because the output from -v
is sent to stderr, not stdout. By redirecting this to a subshell, we can sed
it to remove lines that start with *
. Since the real output does not pass through the subshell, it is not affected. Using a subshell is a little heavy-handed, but it's the easiest way to redirect stderr to another command. (As I noted, I'm only using this for testing, so it works fine for me.)

- 868
- 8
- 14
If you want more alternatives, You can try installing a Modern command line HTTP client like httpie which is available for most of the Operating Systems with package managers like brew, apt-get, pip, yum etc
eg:- For OSX
brew install httpie
Then you can use it on command line with various options
http GET https://www.google.com

- 3,634
- 2
- 27
- 27
the -v option for curl is too verbose in the error output which contains the leading *
(status line) or >
(request head field) or <
(response head field). to get only the request head field:
curl -v -sS www.stackoverflow.com 2>&1 >/dev/null | grep '>' | cut -c1-2 --complement
to get only the request head field:
curl -v -sS www.stackoverflow.com 2>&1 >/dev/null | grep '<' | cut -c1-2 --complement
or to dump it into /tmp/test.txt
file with the -D option
curl -D /tmp/test.txt -sS www.stackoverflow.com > /dev/null
in order to filter the -v
output, you should direct the error output to terminal and the std output to /dev/null, the -s option is to forbid the progress metering

- 1,998
- 3
- 27
- 43