How to debug HTTP requests with cURL

Debugging an API call or site request often depends on seeing the exact HTTP exchange instead of only the response body. Redirects, TLS negotiation, request headers, and method changes can all explain a failure before the application payload becomes the real problem.

In cURL, --verbose prints transport notes plus the request and response header lines on stderr, while --head limits the request to HTTP headers only. When the request body or response body must be inspected as part of the same capture, --trace-ascii writes a full ASCII trace and --trace-time adds timestamps to each event.

Verbose and trace logs can expose bearer tokens, cookies, signed URLs, and raw request bodies. If a local ~/.curlrc changes the request shape, rerun the same command with --disable so the capture reflects only the options shown on the command line, and remove saved traces when the check is finished.

Steps to debug HTTP requests with cURL:

  1. Run the request with --verbose and send the response body to /dev/null so the transport exchange stays readable.
    $ curl --silent --show-error --verbose --output /dev/null https://httpbin.org/anything
    * Host httpbin.org:443 was resolved.
    * IPv6: (none)
    * IPv4: 3.228.76.52, 3.220.42.21, 3.217.55.179, 3.234.199.80, 18.235.15.99, 98.84.87.4
    *   Trying 3.228.76.52:443...
    * Connected to httpbin.org (3.228.76.52) port 443
    ##### snipped #####
    > GET /anything HTTP/2
    > Host: httpbin.org
    > User-Agent: curl/8.7.1
    > Accept: */*
    >
    * Request completely sent off
    < HTTP/2 200
    < date: Wed, 22 Apr 2026 03:39:59 GMT
    < content-type: application/json
    < content-length: 342
    ##### snipped #####
    * Connection #0 to host httpbin.org left intact

    In verbose output, > lines are request headers sent by cURL, < lines are response headers from the server, and * lines describe connection activity.

  2. Repeat the same check with --head when only the status line and response headers matter.
    $ curl --silent --show-error --head --verbose --output /dev/null https://httpbin.org/anything
    * Host httpbin.org:443 was resolved.
    ##### snipped #####
    > HEAD /anything HTTP/2
    > Host: httpbin.org
    > User-Agent: curl/8.7.1
    > Accept: */*
    >
    * Request completely sent off
    < HTTP/2 200
    < date: Wed, 22 Apr 2026 03:39:59 GMT
    < content-type: application/json
    < content-length: 343
    ##### snipped #####
    * Connection #0 to host httpbin.org left intact

    --head changes the request method to HEAD, so use the normal request form when the server behaves differently for GET, POST, or another method.

  3. Save a full ASCII trace when the request body or response body must be inspected together with the headers.
    $ curl --silent --show-error --trace-time --trace-ascii request.trace --output /dev/null --json '{"mode":"audit"}' https://httpbin.org/anything

    --trace-ascii writes the full exchange to a file, and --trace-time makes it easier to line the request up with server-side logs.

  4. Read the saved trace and confirm that the request line, request body, and final status appear in the same capture.
    $ cat request.trace
    11:39:46.542717 => Send header, 146 bytes (0x92)
    0000: POST /anything HTTP/2
    0017: Host: httpbin.org
    002a: User-Agent: curl/8.7.1
    0042: Content-Type: application/json
    0062: Accept: application/json
    007c: Content-Length: 16
    0090:
    11:39:46.542758 => Send data, 16 bytes (0x10)
    0000: {"mode":"audit"}
    ##### snipped #####
    11:39:46.768278 <= Recv header, 13 bytes (0xd)
    0000: HTTP/2 200
    11:39:46.768320 <= Recv header, 32 bytes (0x20)
    0000: content-type: application/json

    The trace is ready to compare with server logs when the same file shows the sent request body and the final HTTP status returned by the endpoint.

  5. Remove the saved trace after the debugging session is complete.
    $ rm -f request.trace

    Trace files can contain raw credentials, cookies, and request bodies, so keep them local and delete them when they are no longer needed.