Convert Curl to a Raw HTTP Request

Every curl command turns into a few lines of text sent over a socket. Seeing that text settles most arguments about what a request "really" contained, and it is the form you need for bug reports, proxies and security tools.

Last updated . How this page is checked.

The command

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

What the flags do

FlagWhat it does
-vShow request headers (>), response headers (<) and connection notes (*).
--trace-ascii fileWrite everything sent and received, bodies included. Use - for the terminal.
--trace fileThe same as a hex dump, for binary bodies.
--http1.1Force 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

More under Converting curl

References

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.