Troubleshooting flaky APIs or unexpected browser-like behavior often requires seeing the raw HTTP conversation between client and server. Detailed request and response data shows exact status codes, redirects, and headers such as Authorization, Set-Cookie, and Cache-Control. Inspecting this traffic clarifies whether a failure originates in the client, the network, or the remote service.
The curl command-line client exposes this detail with verbose and trace options that print connection events, TLS negotiation, and the full wire-level payload. Flags such as --verbose, --head, --include, and --trace-ascii annotate what is being sent and received, using consistent markers for metadata, headers, and body bytes. Combining these options provides both high-level summaries and low-level traces for any HTTP endpoint reachable from the host.
Verbose curl output and trace logs can contain sensitive information, including bearer tokens, cookies, query parameters, and portions of request or response bodies. Debugging should therefore take place on trusted machines, with logs stored in restricted directories and removed or redacted before sharing with others. The following commands assume curl is available in a shell environment on Linux, macOS, or Windows and that the working directory is writable for temporary trace files.
Steps to debug HTTP requests with curl:
- Check the installed curl version to confirm protocol and feature support.
$ curl --version curl 8.7.1 (x86_64-pc-linux-gnu) libcurl/8.7.1 OpenSSL/3.0.13 zlib/1.3.1 Release-Date: 2024-03-27 Protocols: dict file ftp ftps http https imap imaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp Features: alt-svc AsynchDNS GSS-API HTTP2 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets ##### snipped #####
Protocol and feature lines indicate whether HTTP2, proxies, and TLS backends are available, which can influence how debug output appears.
- Send a verbose GET request to observe connection setup, request headers, and the initial response status.
$ curl --verbose https://example.com/ * Trying 93.184.216.34:443... * Connected to example.com (93.184.216.34) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 ##### snipped ##### > GET / HTTP/1.1 > Host: example.com > User-Agent: curl/8.7.1 > Accept: */* ##### snipped ##### < HTTP/2 200 < content-type: text/html; charset=UTF-8 < content-length: 648 ##### snipped #####
Lines prefixed with * describe connection events, lines prefixed with > show outgoing HTTP data, and lines prefixed with < show response headers from the server.
- Focus on status codes and headers without downloading the body by issuing a verbose HEAD request.
$ curl --verbose --head https://example.com/ ##### snipped ##### > HEAD / HTTP/1.1 > Host: example.com ##### snipped ##### < HTTP/2 301 < location: https://www.example.com/ < cache-control: max-age=3600 < content-type: text/html; charset=UTF-8 ##### snipped #####
HEAD requests are efficient for investigating redirect behavior, cache settings, and content negotiation because only metadata is transferred.
- Capture a complete ASCII trace with timestamps into a log file for deeper inspection of a problematic endpoint.
$ curl --verbose --trace-ascii debug-http.log --trace-time https://example.com/api/resource * Trying 93.184.216.34:443... * Connected to example.com (93.184.216.34) port 443 (#0) ##### snipped #####
Trace logs such as debug-http.log can contain cookies, bearer tokens, and request payloads, so store them on trusted systems and remove them after debugging to avoid leaking secrets.
- Inspect the beginning of the trace log to confirm that connection metadata and timestamps were recorded.
$ head -n 12 debug-http.log == Info: Trying 93.184.216.34:443... == Info: Connected to example.com (93.184.216.34) port 443 (#0) == Info: TLSv1.3 (OUT), TLS handshake, Client hello (1): ##### snipped #####
Markers like == Info:, => Send header, and <= Recv header label diagnostic events and differentiate them from raw protocol bytes.
- Verify the request behavior by searching the trace log for HTTP status lines and key headers that match expectations.
$ grep -E '^< HTTP/|^< Location:|^< Content-Type:' debug-http.log < HTTP/2 200 < Content-Type: application/json < Location: https://api.example.com/v2/resource ##### snipped #####
Successful behavior typically shows expected status codes such as 200 or 204, correct Location targets for redirects, and a Content-Type consistent with the API contract.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
Comment anonymously. Login not required.
