192

As an example, POSTing to a web server with the -v argument:

curl -v http://testserver.com/post -d "firstname=john&lastname=doe"

And the output

> POST /post HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
> Host: testserver.com
> Accept: */*
> Content-Length: 28
> Content-Type: application/x-www-form-urlencoded
> 
< HTTP/1.1 200 OK
(etc)

There is no mention of the data that I posted.

Is there an option in cURL to display the string "firstname=john&lastname=doe" in the output?

Note: Obviously the string I want is in the command I executed, but there are several other post options such as --form and --data-ascii etc. I'd like to see the raw data being sent to the server.

Hennes
  • 64,768
  • 7
  • 111
  • 168
gak
  • 8,597
  • 10
  • 27
  • 29
  • 1
    You can also run tcpdump to capture the actual data being sent to the server. Or wireshark (better) if you have that. – Keith Jun 01 '11 at 09:15
  • I'm not sure you can. Is this an example of security by obscurity? - http://stackoverflow.com/questions/198462/get-versus-post-in-terms-of-security – slotishtype Jun 01 '11 at 09:24

5 Answers5

232

The closest I got without using tcpdump is using the --trace-ascii option:

~ curl http://w3.org/ -d "hello=there" --trace-ascii /dev/stdout
== Info: About to connect() to w3.org port 80 (#0)
== Info:   Trying 128.30.52.45... == Info: connected
== Info: Connected to w3.org (128.30.52.45) port 80 (#0)
=> Send header, 210 bytes (0xd2)
0000: POST / HTTP/1.1
0011: User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.1
0051: 9.7 OpenSSL/0.9.8l zlib/1.2.3
0070: Host: w3.org
007e: Accept: */*
008b: Content-Length: 11
009f: Content-Type: application/x-www-form-urlencoded
00d0: 
=> Send data, 11 bytes (0xb)
0000: hello=there

Unfortunately, this doesn't work when you're posting multipart/form-data:

~ curl http://w3.org/ -F hello=there -F testing=123 --trace-ascii /dev/stdout
== Info: About to connect() to w3.org port 80 (#0)
== Info:   Trying 128.30.52.45... == Info: connected
== Info: Connected to w3.org (128.30.52.45) port 80 (#0)
=> Send header, 270 bytes (0x10e)
0000: POST / HTTP/1.1
0011: User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.1
0051: 9.7 OpenSSL/0.9.8l zlib/1.2.3
0070: Host: w3.org
007e: Accept: */*
008b: Content-Length: 244
00a0: Expect: 100-continue
00b6: Content-Type: multipart/form-data; boundary=--------------------
00f6: --------19319e4d1b79
010c: 
<= Recv header, 32 bytes (0x20)
0000: HTTP/1.1 301 Moved Permanently
gak
  • 8,597
  • 10
  • 27
  • 29
  • 5
    I know it is your own answer, but I think you can accept this as the correct answer. It solved it for me anyway, thanks :-) – Darren Cook May 06 '12 at 02:49
  • @DarrenCook It's been a while--I didn't even realise this question wasn't answered! – gak May 06 '12 at 03:31
  • 6
    Remove any `-v` or `--verbose` as they override the trace directive. – AlikElzin-kilaka Feb 17 '14 at 14:56
  • It doesn't work with https either as the data is encrypted ... :( – Augustin Riedinger Apr 17 '14 at 08:52
  • 3
    @AugustinRiedinger It works fine with https. I just tried it and saw the payload. The data is encrypted but since you are the endpoint of the connection, you have all the data available to you, and therefore curl can see it. – gak Aug 29 '14 at 01:18
  • 2
    Using `--trace-ascii` worked for me on OS X 10.8.5 Mountain Lion. I have uploaded a multipart form entity with two images and a json body and everything worked as expected – Heath Borders Sep 04 '14 at 21:13
  • The `--trace-ascii` works for me on Cygwin for multipart data as well! – CMCDragonkai Apr 16 '16 at 15:29
  • 8
    Instead of `--trace-ascii /dev/stdout` you can `--trace-ascii -` (dash) – Adam Michalik Sep 07 '16 at 11:40
  • Any idea how to pass `--trace-ascii` to curl while accessing it from PHP code? I could not find any equivalent option @ http://php.net/manual/en/function.curl-setopt.php – Vivek Athalye Mar 31 '18 at 18:25
51

Or you could test with https://httpbin.org/

$ curl https://httpbin.org/post -d "firstname=john&lastname=doe"
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "firstname": "john", 
    "lastname": "doe"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "27", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/7.43.0"
  }, 
  "json": null, 
  "origin": "*.*.*.*", 
  "url": "https://httpbin.org/post"
}
  • While this is not useful to see actual data sent like Gert's answer, it is useful that it parses the response so one can know whether there is format error. – akostadinov Mar 18 '22 at 18:56
28

Would like to add netcat alternative

#!/bin/bash
nc -l 8080 &

curl "http://localhost:8080" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
--data @- <<EOF
{
  "me": "$USER",
  "something": $(date +%s)
}
EOF
Gert Cuykens
  • 587
  • 5
  • 13
23

--trace - works with curl 7.58 and shows you the POST body:

$ curl --trace - -d 'foo=bar' http://example.org
== Info: Rebuilt URL to: http://example.org/
== Info:   Trying 2606:2800:220:1:248:1893:25c8:1946...
== Info: TCP_NODELAY set
== Info: Connected to example.org (2606:2800:220:1:248:1893:25c8:1946) port 80 (#0)
=> Send header, 144 bytes (0x90)
0000: 50 4f 53 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d POST / HTTP/1.1.
0010: 0a 48 6f 73 74 3a 20 65 78 61 6d 70 6c 65 2e 6f .Host: example.o
0020: 72 67 0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 rg..User-Agent: 
0030: 63 75 72 6c 2f 37 2e 35 38 2e 30 0d 0a 41 63 63 curl/7.58.0..Acc
0040: 65 70 74 3a 20 2a 2f 2a 0d 0a 43 6f 6e 74 65 6e ept: */*..Conten
0050: 74 2d 4c 65 6e 67 74 68 3a 20 37 0d 0a 43 6f 6e t-Length: 7..Con
0060: 74 65 6e 74 2d 54 79 70 65 3a 20 61 70 70 6c 69 tent-Type: appli
0070: 63 61 74 69 6f 6e 2f 78 2d 77 77 77 2d 66 6f 72 cation/x-www-for
0080: 6d 2d 75 72 6c 65 6e 63 6f 64 65 64 0d 0a 0d 0a m-urlencoded....
=> Send data, 7 bytes (0x7)
0000: 66 6f 6f 3d 62 61 72                            foo=bar
== Info: upload completely sent off: 7 out of 7 bytes
<= Recv header, 17 bytes (0x11)
0000: 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.
0010: 0a                                              .
<= Recv header, 22 bytes (0x16)
cweiske
  • 1,857
  • 2
  • 25
  • 38
  • This is the best answer, because it also works for mulitpart/form-data requests, without having to use a third party proxy – nobody Apr 20 '21 at 13:02
9

You could use Charles and curl --proxy localhost:8888. Simples!

Dori
  • 375
  • 3
  • 9