Curl Verbose Example

-v makes curl narrate the whole exchange: the connection it opened, the request it sent and the response headers that came back. It is the first thing to add when a request misbehaves, and most of its value is in knowing which of three kinds of line you are looking at.

Last updated . How this page is checked.

The command

curl -v https://httpbin.org/get

Flags that show more, or less

FlagWhat it does
-v, --verboseConnection details, request headers and response headers, written to stderr.
-i, --includeResponse headers in front of the body, on stdout. No request headers.
-I, --headSends a HEAD request, so only response headers come back.
-D fileSaves the response headers to a file. Use -D - for stdout.
--trace-ascii fileEverything -v shows plus the bodies in both directions, as text.
--trace fileThe same as a hex dump, for binary data.
--trace-timePuts a timestamp in front of every verbose or trace line.
-w formatPrints chosen facts after the transfer, such as the status code or timings.
-s, --silentHides the progress meter and error messages. Add -S to keep the errors.

The three kinds of line

Every line of verbose output starts with a marker. An asterisk is curl talking about itself: the address it resolved, the connection it opened, the TLS version and certificate it negotiated, whether it reused a connection. A greater-than sign is a header line curl sent. A less-than sign is a header line it received. Lines with no marker are the response body, which is not part of the verbose output at all and is simply being printed as usual.

Read them in that order when something fails. If the asterisk lines stop early, the problem is the network or TLS and no request was ever sent. If the request lines are not what you intended, the problem is your command: a header missing, a method changed by a flag. If both look right, the answer is in the response headers.

$ curl -v https://example.com/
* Host example.com:443 was resolved.
*   Trying 203.0.113.10:443...
* Connected to example.com (203.0.113.10) port 443
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* Server certificate:
*  subject: CN=example.com
*  expire date: ...
*  SSL certificate verify ok.
> GET / HTTP/2
> Host: example.com
> User-Agent: curl/8.5.0
> Accept: */*
>
< HTTP/2 200
< content-type: text/html; charset=UTF-8
< content-length: 1256
<
<!doctype html>
...

Verbose output goes to stderr

Curl writes the body to standard output and the verbose lines to standard error. That split is what lets you pipe the body into another program with -v switched on and not corrupt it. It is also why curl -v … | grep appears to find nothing: the pipe carries only stdout. Merge the two streams with 2>&1 to search the verbose text, or point stderr at a file to keep a log beside the normal output.

# only the header lines, sent and received
curl -sS -o /dev/null -v https://httpbin.org/get 2>&1 | grep -E '^[<>]'

# keep the body on screen, save the conversation
curl -v https://httpbin.org/get 2> verbose.log

When you only want the headers or the status

Verbose mode is more than you need for the commonest question, which is what the server answered. -i prints the status line and response headers above the body. -D - with the body discarded gives the response headers of a real GET, which can differ from what a HEAD request returns. And a -w format prints the status code alone, which is the form to use in a script.

curl -i https://httpbin.org/status/204
curl -sS -D - -o /dev/null https://httpbin.org/get
curl -sS -o /dev/null -w '%{http_code}\n' https://httpbin.org/status/404

Seeing the request body: --trace-ascii

-v shows the headers curl sent and never the body it sent after them. When the question is whether your JSON left the machine intact, or what a -d value looked like after the shell had finished with it, use --trace-ascii. It logs every byte in both directions with a line saying which direction and how many bytes. Give it a file name, or a dash to print to the terminal. --trace-time adds a timestamp to each line, which shows where a slow request spends its time: a gap before the first received header is the server working, a gap before the connection line is the network.

curl --trace-ascii - -H 'Content-Type: application/json' -d '{"name":"Ada"}' https://httpbin.org/post

curl -v --trace-time https://httpbin.org/delay/1

Timing without the noise

For numbers instead of a log, -w reports how long each phase took, as seconds counted from the start of the request. Subtract neighbouring values to get the length of a phase: the TLS handshake is the difference between the connect and appconnect figures.

curl -sS -o /dev/null https://httpbin.org/get \
  -w 'dns %{time_namelookup}  tcp %{time_connect}  tls %{time_appconnect}  first byte %{time_starttransfer}  total %{time_total}\n'

Common mistakes

  • Verbose output contains your credentials. The Authorization header and cookies you sent are among the request lines. Remove them before pasting a log into a ticket or a chat.
  • Expecting the request body in -v. It is not there. Use --trace-ascii.
  • Combining -v with --trace. They are alternatives; curl uses one and warns about the other.
  • Reading HTTP/2 output with HTTP/1.1 expectations. Header names are lower case and the status line has no reason phrase: < HTTP/2 200, not 200 OK.
  • Using -s alone in a script. It hides error messages as well as the progress meter, so a failure prints nothing. Write -sS.

Related curl examples

More under Network behaviour

References

These links leave api-tester.com, which is independent of the projects they point to.

FAQ

What does curl -v do?

It turns on verbose mode. Curl prints details of the connection, the request headers it sends and the response headers it receives, each line marked with *, > or <. The output goes to stderr and the body still goes to stdout.

What do the *, > and < symbols mean in curl verbose output?

An asterisk marks informational lines from curl itself, such as DNS, connection and TLS details. A greater-than sign marks request headers sent to the server, and a less-than sign marks response headers received from it.

How do I show only the response headers in curl?

Use curl -I to send a HEAD request, or curl -sS -D - -o /dev/null to send a normal GET and print only its headers. Use curl -i to print the headers followed by the body.

How do I see the request body curl sent?

Use --trace-ascii followed by a file name, or a dash for the terminal. Unlike -v, it logs the bodies as well as the headers in both directions.

Why can I not grep the output of curl -v?

Because verbose output is written to stderr and a pipe carries only stdout. Add 2>&1 before the pipe to merge the two streams.