Skip to content

Watching the Conversation

-i shows you the reply. -v shows you the conversation: your request going out, the reply coming back, and curl's own running commentary on connecting, authenticating, and closing. When something fails and the body won't say why, this is where the why lives. It is the single most useful debugging option curl has.

$ curl -v http://127.0.0.1:8901/hello
*   Trying 127.0.0.1:8901...
* Connected to 127.0.0.1 (127.0.0.1) port 8901
> GET /hello HTTP/1.1
> Host: 127.0.0.1:8901
> User-Agent: curl/8.5.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: CurlLab/1.0
< Date: Tue, 20 Oct 2026 00:48:07 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 27
<
{ [27 bytes data]
* Connection #0 to host 127.0.0.1 left intact
Hello from the lab server.

(Capture trimmed: the progress meter and a line reporting proxy environment variables are left out. On a machine whose shell sets http_proxy and friends, -v names them in its first lines — worth knowing before you conclude a site is "down" when your proxy is.)

Reading the directions

Every line carries a one-character compass:

Mark Means
* curl talking about itself: connecting, TLS, closing
> sent by you: your request line and headers
< received: the server's status line and headers
{ / } data (body bytes) going out / coming in

The story in the capture, in order: curl tries the address and connects (the * lines); sends a request — GET /hello HTTP/1.1, asking for the /hello page by the HTTP method GET — with three headers of its own devising: Host (which site on that machine; required, and the server may answer differently per name), User-Agent (curl introducing itself, honestly, as curl/8.5.0), and Accept: */* ("I'll take anything"). A lone > line ends your half: the blank line that says headers over.

Then the reply (< lines — chapter 2's headers, seen arriving), a { [27 bytes data] note standing in for the body itself, and the body printed last, after curl notes it left the connection open for reuse.

Things -v settles at a glance on a bad day: whether you connected to the address you meant (the Trying line), whether the server saw the path and headers you think you sent (the > lines), whether it redirected you somewhere unexpected (a 3xx in the < lines), and whose name is on the certificate when TLS is involved (chapter 8 reads those * lines).

Keeping it: --trace-ascii

-v scrolls past. --trace-ascii writes the same conversation to a file, in numbered, timestamp-free plain text, with each chunk's offset and size recorded:

$ curl -s --trace-ascii trace.txt http://127.0.0.1:8901/hello
Hello from the lab server.
$ cat trace.txt
== Info:   Trying 127.0.0.1:8901...
== Info: Connected to 127.0.0.1 (127.0.0.1) port 8901
=> Send header, 82 bytes (0x52)
0000: GET /hello HTTP/1.1
0015: Host: 127.0.0.1:8901
002b: User-Agent: curl/8.5.0
0043: Accept: */*
0050:
<= Recv header, 17 bytes (0x11)
0000: HTTP/1.1 200 OK
...
<= Recv data, 27 bytes (0x1b)
0000: Hello from the lab server..
== Info: Connection #0 to host 127.0.0.1 left intact

(One sandbox proxy-notice line trimmed from the head; the response headers, identical to the -i capture in chapter 2, are elided with ....) The offsets on the left — 0000, 0015, 002b — are byte positions, in hexadecimal. They matter when a server is picky about exactly what arrived: the trace proves the bytes, not your intentions. Note the body's final characters rendered as .. — non-printing bytes (the line ending) shown as dots, which is what makes the ASCII trace safe to keep in a log or paste into a bug report.

--trace (without -ascii) adds a hex dump beside the text — the tool for binary protocols and for proving a byte is really a zero. --trace-time prefixes timestamps when the question is when, not what.

Which watcher when

Situation Reach for
"What did it send back?" -i
"Why did that fail?" -v
"I need to show someone / keep it" --trace-ascii
"Something binary is wrong" --trace
"Just the facts, for a script" -sS + -w (ch. 9)

One caution that applies to every watcher: traces contain secrets. Headers include your Authorization header, cookies include session values. A trace is a specimen only when the credentials are; before pasting a real one anywhere, read it the way chapter 5 teaches you to read anything bearing tokens.

Check: curl -v on the lab shows your three default request headers between the > marks and the reply between the < marks; a trace file written by --trace-ascii records the same exchange with byte offsets; and neither changes what the server received — watching is free.

Next: putting something in the request — data, forms, and files.