The command
curl -v -H "Content-Type: application/json" -d '{"name":"Ada"}' https://httpbin.org/post
What the flags do
| Flag | What it does |
|---|---|
-v | Show request headers (>), response headers (<) and connection notes (*). |
--trace-ascii file | Write everything sent and received, bodies included. Use - for the terminal. |
--trace file | The same as a hex dump, for binary bodies. |
--http1.1 | Force HTTP/1.1, whose messages are plain text. |
From command to message
The command above, forced to HTTP/1.1, produces the request below. The first line is the method, path and protocol version; the URL's hostname has moved into the Host header. Then come the headers, a blank line, and the body. Three of these headers were never typed: Host, User-Agent and Accept are added by curl, and Content-Length is calculated from the body.
POST /post HTTP/1.1
Host: httpbin.org
User-Agent: curl/8.5.0
Accept: */*
Content-Type: application/json
Content-Length: 14
{"name":"Ada"}
Reading -v and getting the body too
-v writes its commentary to standard error, so the response body on standard output stays clean; redirect one or the other to separate them. It shows headers but not the request body. For the complete exchange, including exactly what bytes of body went out, use --trace-ascii. That is the tool for catching a body the shell altered through quoting.
curl -v --http1.1 -o /dev/null -d '{"name":"Ada"}' https://httpbin.org/post 2>&1 | grep "^[<>]"
curl --trace-ascii - --http1.1 -d '{"name":"Ada"}' https://httpbin.org/post
HTTP/2 looks different
Most HTTPS servers negotiate HTTP/2, which is a binary protocol. There is no request line; curl shows its parts as pseudo-headers such as :method, :path and :authority (which replaces Host), and all header names are lower case. The meaning is identical. When you need a textual message to paste somewhere, add --http1.1.
To go the other direction and send a hand-written request, you need a raw socket tool; over TLS that is openssl s_client.
printf 'GET /get HTTP/1.1\r\nHost: httpbin.org\r\nConnection: close\r\n\r\n' \
| openssl s_client -quiet -connect httpbin.org:443 -servername httpbin.org
Common mistakes
- Trace output contains credentials. Authorization headers, cookies and bodies are written in full. Redact before sharing.
- Lines end in CRLF. A raw request written with bare newlines is malformed, and strict servers reject it.
- What the server receives may differ again if a proxy or load balancer adds, renames or strips headers on the way.
Related curl examples
Curl Send Header Example
-H adds a header line to the request.
Convert Curl to Python Requests
A curl command and a call to the requests library describe the same HTTP request in different vocabularies.
Curl HTTPS Request Example
An https:// URL is all curl needs to use TLS, and it verifies the server's certificate by default.
How to Use Curl
Curl is a command-line program that makes network requests and prints what comes back.
cURL Converter
Turn a curl command into code for nine targets.
HTTP Headers
What the common request and response headers mean.
All Curl Examples
49 worked examples, grouped by what you are trying to do.
More under Converting curl
References
- curl man page: -v — Printing the request and response headers.
- MDN: HTTP messages — The structure of a request and a response on the wire.
These links leave api-tester.com, which is independent of the projects they point to.
FAQ
How do I see the raw HTTP request curl sends?
Run the command with -v to see the request line and headers, or with --trace-ascii - to see the complete request including the body.
What headers does curl send by default?
Host, User-Agent (curl/version) and Accept: */*. When a body is sent it also adds Content-Length and, for -d, Content-Type: application/x-www-form-urlencoded.
How do I convert a curl command to an HTTP request?
Take the method, path and HTTP version as the first line, add a Host header with the hostname, list the headers from each -H flag plus curl's defaults, then a blank line and the body from -d.