What is curl?
curl is an open-source command-line tool for transferring data with URLs, and libcurl is the library behind it, embedded in a very wide range of operating systems, devices and applications. It is released under an MIT-style license. For API work it is the lowest common denominator: every API documentation site shows curl examples, every platform has it, and a curl command is the most portable way to hand someone a reproducible request. It speaks HTTP/0.9 through HTTP/3 and over two dozen other protocols, and supports authentication schemes from Basic and Digest to Bearer tokens and AWS SigV4.
Why use it in the API Lifecycle?
- Reproducible requests: A single command captures method, URL, headers and body, which makes it the standard format for bug reports and documentation examples.
- Full HTTP control: Custom methods (
-X), arbitrary headers (-H), HTTP version selection (--http1.1,--http2,--http3), redirect following (-L) and ranges (-r). - JSON shortcut:
--json(since 7.82.0) posts a body withContent-Type: application/jsonandAccept: application/jsonset for you. - Wire-level visibility:
-v,--trace-asciiand-Dshow exactly what was sent and received, including TLS negotiation and response headers. - Scriptable checks:
-w '%{response_code}'and other write-out variables expose status, timings and sizes for shell scripts and health checks. - Connection control:
--resolveand--connect-tosend a request to a specific IP or host while keeping the originalHostand TLS name, which is how you test a server behind a load balancer or CDN.
Best Practices
- Use
--fail-with-body(since 7.76.0) in scripts and CI. Without it curl exits 0 on a500 Internal Server Error; with plain--failit exits 22 but discards the body, which is usually the Problem Details document that explains the failure. - Debug with
-vor--trace-ascii -, not just the body. Most API bugs are in headers: a missingContent-Type, aVarythat defeats caching, or a redirect that dropsAuthorization. - Use
--retryfor transient failures in scripts. It retries timeouts and408,429,500,502,503and504, and honorsRetry-After. Avoid--retry-all-errorson non-idempotent requests; curl’s own documentation warns it can duplicate data. See Retries and Backoff. - Keep tokens out of shell history and process lists. Read headers from a file with
-H @headers.txt, or use--variableand--expand-header(since 8.3.0) to pull a value from an environment variable, instead of typing-H "Authorization: Bearer ..."inline. - Test conditional requests with
--etag-saveand--etag-compareto confirm the server returns304 Not Modifiedfor an unchangedETag. See Conditional Requests. - Add
--compressedwhen checking response size or caching. Without it curl does not sendAccept-Encoding, so you see the uncompressed path that real clients rarely take. - Time requests with
-wvariables such as%{time_connect},%{time_starttransfer}and%{time_total}to separate network and TLS cost from server processing time. - For repeatable suites rather than one-off checks, move to Hurl, which runs on libcurl and adds captures and assertions in a plain-text file.