How can I see the request headers made by curl when sending a request to the server?
Asked Answered
G

15

596

I want to see the request headers made by curl when I am sending a request to the server. How can I check that?

Gulden answered 15/5, 2009 at 4:10 Comment(2)
this url may be helpful. helloacm.com/curlJostle
You can use this to test run-node.com/now-use-curl-with-http-echo-comKinakinabalu
R
616

I think curl --verbose/-v is the easiest. It will spit out the request headers (lines prefixed with '>') without having to write to a file:

$ curl -v -I -H "Testing: Test header so you see this works" http://stackoverflow.com/
* About to connect() to stackoverflow.com port 80 (#0)
*   Trying 69.59.196.211... connected
* Connected to stackoverflow.com (69.59.196.211) port 80 (#0)
> HEAD / HTTP/1.1
> User-Agent: curl/7.16.3 (i686-pc-cygwin) libcurl/7.16.3 OpenSSL/0.9.8h zlib/1.2.3 libssh2/0.15-CVS
> Host: stackoverflow.com
> Accept: */*
> Testing: Test header so you see this works
>
< HTTP/1.0 200 OK
...
Rael answered 25/6, 2010 at 20:21 Comment(5)
curl -v -D - stackoverflow.com -o /dev/null (in order to do not display whole site's content, just headers)Balsa
curl -Ivs http://example.com > /dev/null : -I for a HEAD request, -v to show sent headers, -s to hide progress bar, > /dev/null to show only the -v output, avoiding duplication.Bromate
@PiotrekDe -D - was neat, but was not useful to me as it simply duplicated the headers that -v already displayed. If you want them unprefixed for automated machine consumption, then maybe it would be better in that case, but I only wanted to glimpse at what a problem was in more detail.Dippy
There are two very helpful feature of the "verbose" flag: first, it also prints the TLS handshake process when accessing website through HTTPS, such as curl -v https://www.example.com; second, it also prints the CONNECT request if you are visiting the site through HTTP proxy, such as curl --proxy my-proxy:8080 http://www.example.com. I believe it would help more users if some examples of these two features are mentioned in this answer.Fold
TL;DR: Don't use -I In the modern world, when people ask about seeing headers, they are probably talking about APIs. And if you use that "I use -I to see the headers with my Apache webserver" mentality, you are going to waste a lot of time developing against a HEAD method when you probably mean to use GET. Stop telling people to use -I. If they want HEAD, use -X HEAD (TWSS)Acceptable
P
144

The question did not specify if command line command named curl was meant or the whole cURL library.

The following PHP code using cURL library uses first parameter as HTTP method (e.g. "GET", "POST", "OPTIONS") and second parameter as URL.

<?php
$ch = curl_init();
$f = tmpfile(); # will be automatically removed after fclose()
curl_setopt_array($ch, array(
    CURLOPT_CUSTOMREQUEST  => $argv[1],
    CURLOPT_URL            => $argv[2], 
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_FOLLOWLOCATION => 0,
    CURLOPT_VERBOSE        => 1,
    CURLOPT_HEADER         => 0,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_STDERR         => $f,
));
$response = curl_exec($ch);
fseek($f, 0);
echo fread($f, 32*1024); # output up to 32 KB cURL verbose log
fclose($f);
curl_close($ch);
echo $response;

Example usage:

php curl-test.php OPTIONS https://google.com

Note that the results are nearly identical to following command line

curl -v -s -o - -X OPTIONS https://google.com
Phono answered 10/12, 2010 at 6:18 Comment(7)
This is the best answer, because the file used in this method contains everything in curl_getinfo() referenced below, along with more details on both the request and the response.Tadich
Nice! Any way to improve the code to show the POST data as well? I.e. that added by curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);Crabtree
This makes no sense. CURLOPT_STDERR makes curl write errors in the stream $f, not the request data. And that's why it didn't work for me. Unless I'm missing something important?Excision
You can use CURLOPT_WRITEHEADER for the header information and CURLOPT_FILE for the whole transferChinese
Bear in mind that if the connection is refused files that were specified with CURLOPT_WRITEHEADER and CURLOPT_FILE are empty.Theodolite
Who said anything about using php?Pershing
Ive upvoted your answer because while the question was not php related, your php based answer pointed me into the right direction for solving my own issue with sending a bearer token. Thank you. I stated my reason here only in the vain attempt to have this question show up in future google searches for php devs with a similar issue.Podite
G
72

The --trace-ascii option to curl will show the request headers, as well as the response headers and response body.

For example, the command

curl --trace-ascii curl.trace http://www.google.com/ 

produces a file curl.trace that starts as follows:

== Info: About to connect() to www.google.com port 80 (#0)
== Info:   Trying 209.85.229.104... == Info: connected
== Info: Connected to www.google.com (209.85.229.104) port 80 (#0)
=> Send header, 145 bytes (0x91)
0000: GET / HTTP/1.1
0010: User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3
0050:  OpenSSL/0.9.7l zlib/1.2.3
006c: Host: www.google.com
0082: Accept: */*
008f: 

It also got a response (a 302 response, to be precise but irrelevant) which was logged.


If you only want to save the response headers, use the --dump-header option:

curl -D file url
curl --dump-header file url

If you need more information about the options available, use curl --help | less (it produces a couple hundred lines of output but mentions a lot of options). Or find the manual page where there is more explanation of what the options mean.

Goggle answered 15/5, 2009 at 4:14 Comment(1)
-D gives you the response headers (as does -I, but to STDIN). The question asked for the request headers.Chiropteran
J
51

curl --trace-ascii {filename} or use a single dash instead of file name to get it sent to stdout:

curl --trace-ascii - {URL}

CURLOPT_DEBUGFUNCTION if you're using libcurl

This shows you everything curl sends and receives, with some extra info thrown in.

Jelly answered 15/5, 2009 at 8:47 Comment(2)
This is very verbose, but certainly shows you everything you should need to know.Tracytrade
This is the only answer that helped me. Some external script was setting some proxy settings and this told me the proxy was being used when it shouldn't have been. Verbose output did not mention the proxy.Frampton
G
51

The only way I managed to see my outgoing headers (curl with php) was using the following options:

curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

Getting your debug info:

$data = curl_exec($ch);
var_dump($data);
var_dump(curl_getinfo($ch));
Give answered 26/1, 2010 at 10:54 Comment(3)
For me that appeared to be the response header not the outgoing header.Airiness
var_dump $data will return the response headers as well as the response body. The var_dump curl_getinfo($ch) will give you the request headers.Rieth
CURLOPT_HEADER is the response header - CURLINFO_HEADER_OUT is the request header. This is what the OP is asking for :)Maggard
R
29

I tried the answers here and found that the most useful and easiest one is not listed as an answer yet, but it is:

curl -v https://example.com/path

This prints out the REQUEST headers as well as the RESPONSE headers plus other useful such as the SSL cert and whether an existing TCP connection was reused. the -v flag can be combined with other flags, of course, such as to follow redirects and prompt for HTTP authentication:

curl -vL --user my_username https://example.com/path

Hope this helps.

Rife answered 26/4, 2016 at 21:16 Comment(1)
It is listed at the topmost placeSeymour
J
26

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 stdout
  • sed - 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 '> ' prefix
  • s/< // - remove '< ' prefix
Junna answered 16/1, 2019 at 20:49 Comment(1)
This almost works perfectly, but it seems to print the response twice because its in both stdout as well as stderror (which you're passing to stdout).Bridgetbridgetown
D
23

I know this is a little late, but my favoured method for doing this is netcat, as you get exactly what curl sent; this can differ from the --trace or --trace-ascii options which won't show non-ASCII characters properly (they just show as dots or need to be decoded).

You can do this as very easily by opening two terminal windows, in the first type:

nc -l localhost 12345

This opens a listening process on port 12345 of your local machine.

In the second terminal window enter your curl command, for example:

curl --form 'foo=bar' localhost:12345

In the first terminal window you will see exactly what curl sent in the request.

Now of course nc won't send anything in response (unless you type it in yourself), so you will need to interrupt the curl command (control-c) and repeat the process for each test.

However, this is a useful option for simply debugging your request, as you're not involving a round-trip anywhere, or producing bogus, iterative requests somewhere until you get it right; once you're happy with the command, simply redirect it to a valid URL and you're good to go.

You can do the same for any cURL library as well, simply edit your request to point to the local nc listener until you're happy with it.

Darrendarrey answered 7/12, 2017 at 12:17 Comment(3)
Upvote this. It's the cleanest way to see with complete confidence exactly what curl is sending. Most people answered some variation on curl -v which basically works, but also dumps tons of other noise, especially for HTTPS.Banerjee
I totally agree with @Yitz. If you are just interested in what was sent by curl (and don't care about the networking details), this is the best way to go.Processional
This worked a treat. Pro tip - if you're on Arch Linux ARM and it doesn't work, use sudo pacman -S openbsd-netcat. See: bbs.archlinux.org/viewtopic.php?id=171551Jonasjonathan
C
6

dump the headers in one file and the payload of the response in a different file

curl -k -v -u user:pass  "url" --trace-ascii headers.txt >> response.txt
Coaction answered 8/8, 2014 at 12:41 Comment(0)
T
5
curl -s -v -o/dev/null -H "Testheader: test" http://www.example.com

You could also use -I option if you want to send a HEAD request and not a GET request.

Twit answered 2/9, 2015 at 13:24 Comment(0)
A
3

Here is my http client in php to make post queries with cookies included:

function http_login_client($url, $params = "", $cookies_send = "" ){

    // Vars
    $cookies = array();
    $headers = getallheaders();

    // Perform a http post request to $ur1 using $params
    $ch = curl_init($url);
    $options = array(   CURLOPT_POST => 1,
                        CURLINFO_HEADER_OUT => true,
                        CURLOPT_POSTFIELDS => $params,
                        CURLOPT_RETURNTRANSFER => 1,
                        CURLOPT_HEADER => 1,
                        CURLOPT_COOKIE => $cookies_send,
                        CURLOPT_USERAGENT => $headers['User-Agent']
                    );

    curl_setopt_array($ch, $options);

    $response = curl_exec($ch);

/// DEBUG info echo $response; var_dump (curl_getinfo($ch)); ///

    // Parse response and read cookies
    preg_match_all('/^Set-Cookie: (.*?)=(.*?);/m', $response, $matches);

    // Build an array with cookies
    foreach( $matches[1] as $index => $cookie )
        $cookies[$cookie] = $matches[2][$index];

    return $cookies;
} // end http_login_client
Amethyst answered 14/10, 2010 at 12:11 Comment(0)
H
3

You can see it by using -iv

$> curl  -ivH "apikey:ad9ff3d36888957" --form  "file=@/home/mar/workspace/images/8.jpg" --form "language=eng" --form "isOverlayRequired=true" https://api.ocr.space/Parse/Image
Hasen answered 23/2, 2017 at 15:38 Comment(0)
K
2

You can use wireshark or tcpdump to look on any network traffic (http too).

Kirkcudbright answered 16/5, 2009 at 9:24 Comment(1)
if the payload is over HTTPS, those are useless without a proxy or application layer monitor.Templas
E
2

You can dump headers directly to stdout by using "-" as the filename - so for example to see headers and content, and follow redirects, all in one output:

curl -L -D - -s [url]
Edifice answered 24/8, 2021 at 10:32 Comment(3)
This was in a previous answer, but since it was at the bottom of a long answer I am upvoting as it's usefulExhaustion
@solbs, yeah, true, I was reading through the answers and missed the other answer that already had it. So upvoting this one too, because it is likely a honest submission from author as well it proved to be useful.Starr
The key is -DPaez
I
1

Make a sample request to https://http-tools.appspot.com/reflect-http-request/some-unique-id and check what this request contains (request header, request body, request parameters) by its corresponding finder url https://http-tools.appspot.com/reflect-http-request-finder/some-unique-id. You can use any string instead of some-unique-id, check out https://http-tools.appspot.com for more details.

Inapproachable answered 15/3, 2016 at 16:19 Comment(1)
Thanks, while not exactly answering the question, this is exactly what I needed. Device A makes a request, Device B checks a request has been made.Squawk

© 2022 - 2024 — McMap. All rights reserved.