Using HTTP/2 with cURL enables faster and more efficient communication with modern APIs and websites by reducing head-of-line blocking and lowering header overhead. Multiplexed streams, header compression via HPACK, and connection reuse help scripts, health checks, and automation hit endpoints with less latency and better throughput.
When compiled with HTTP/2 support, cURL relies on libcurl and a backend such as nghttp2 to negotiate the protocol during the TLS handshake using ALPN. Command-line switches like --http2 and --write-out expose the negotiated protocol version, while verbose logging reveals the underlying handshake, stream setup, and reuse behavior.
Actual behavior depends on how the cURL binary was built, the capabilities of upstream servers and proxies, and whether cleartext h2c is involved. Forcing HTTP/2 on endpoints that only speak HTTP/1.1 results in connection failures, so version support and negotiation details should be checked before baking HTTP/2 flags into production scripts.
Steps to use HTTP/2 in cURL:
- Display local cURL build information to confirm HTTP/2 support.
$ curl --version curl 8.5.0 (x86_64-pc-linux-gnu) libcurl/8.5.0 OpenSSL/3.0.12 zlib/1.2.13 brotli/1.1.0 nghttp2/1.57.0 Release-Date: 2023-12-06 Protocols: dict file ftp ftps http https Features: AsynchDNS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets brotli HSTS ##### snipped #####
Presence of HTTP2 in the Features line confirms that the installed binary can negotiate HTTP/2 connections.
- Send a header-only HTTPS request while explicitly requesting HTTP/2.
$ curl --http2 --head "https://www.example.com/" HTTP/2 200 content-type: text/html; charset=UTF-8 content-length: 1256 server: ExampleServer date: Mon, 01 Jan 2024 12:00:00 GMT ##### snipped #####
A status line beginning with HTTP/2 indicates that the server is responding over HTTP/2 instead of HTTP/1.1.
- Inspect verbose output to observe TLS negotiation and protocol selection details.
$ curl --http2 --verbose "https://www.example.com/" --output /dev/null * Trying 93.184.216.34:443... * Connected to www.example.com (93.184.216.34) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * ALPN, server accepted to use h2 * Using HTTP2, server supports multi-use ##### snipped #####
Lines mentioning ALPN and a message such as Using HTTP2 show that the handshake successfully negotiated HTTP/2.
- Force cleartext HTTP/2 only when targeting a known h2c test endpoint.
$ curl --http2-prior-knowledge "http://h2c.example.net/" ##### snipped #####
Using --http2-prior-knowledge against servers that only understand HTTP/1.1 causes requests to fail because no protocol downgrade is attempted.
- Print only the negotiated HTTP version as a concise machine-readable indication.
$ curl --http2 --silent --output /dev/null --write-out '%{http_version}\n' "https://www.example.com/" 2
Output of 2 from --write-out '{http_version}' shows successful HTTP/2 use, while 1.1 or 1.0 indicates fallback to an older protocol.
- Test multiplexing behavior by fetching multiple URLs over a single connection.
$ curl --http2 --parallel --silent \ "https://www.example.com/" \ "https://www.example.com/about" \ "https://www.example.com/contact" ##### snipped #####
Concurrent transfers with --parallel over HTTP/2 reuse one connection and can reduce total time for multiple small requests.
- Verify fallback behavior by repeating the version check against an endpoint that only supports HTTP/1.1.
$ curl --http2 --silent --output /dev/null --write-out '%{http_version}\n' "http://legacy.example.org/" 1.1
Different outputs for modern and legacy endpoints confirm that scripts using HTTP/2 flags still behave correctly when servers cannot negotiate HTTP/2.
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.
