Using HTTP/2 with cURL is a direct way to confirm that an HTTPS endpoint really negotiates the newer transport before API checks, synthetic probes, or proxy policy start depending on it. A normal request is often enough to prove the protocol version in use, which keeps the check close to real client traffic.

For HTTPS URLs, cURL already offers HTTP/2 during the TLS ALPN negotiation when the local build and the server both support it, so a plain request can return HTTP/2 without any protocol flag. The --http2 option mainly matters when the request uses cleartext HTTP and needs an h2c upgrade attempt, while --http2-prior-knowledge skips that upgrade only for hosts that are already known to speak HTTP/2 directly.

This workflow still depends on both ends of the connection. A cURL build without the HTTP2 feature cannot use these options at all, a server or intermediary can still negotiate down to HTTP/1.1, and --http2-prior-knowledge on HTTPS changed in cURL 8.10.0 so it now offers only HTTP/2 in ALPN instead of both HTTP/2 and HTTP/1.1.

Steps to use HTTP/2 in cURL:

  1. Check the local cURL build for the HTTP2 feature before using protocol-specific flags.
    $ curl --version
    curl 8.7.1 (x86_64-apple-darwin25.0) libcurl/8.7.1 (SecureTransport) LibreSSL/3.3.6 zlib/1.2.12 nghttp2/1.68.0
    Release-Date: 2024-03-27
    Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
    Features: alt-svc AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM SPNEGO SSL threadsafe UnixSockets

    Look for HTTP2 in the Features line. Without it, --http2 and --http2-prior-knowledge cannot negotiate the protocol and a different cURL build is required.

  2. Send a simple HEAD request to an HTTPS endpoint and read the status line to confirm that cURL negotiated HTTP/2 automatically.
    $ curl --silent --show-error --head https://curl.se/
    HTTP/2 200
    server: nginx/1.27.5
    content-type: text/html
    last-modified: Wed, 22 Apr 2026 02:05:02 GMT
    etag: "2c81-65002f5b81d2b"
    ##### snipped #####

    For HTTPS URLs, this is the normal starting point because cURL already offers HTTP/2 by default when the remote side supports it.

  3. Print the negotiated protocol and final status in one line when a script or health check needs a clean assertion.
    $ curl --silent --show-error --output /dev/null --write-out 'HTTP/%{http_version} %{response_code}\n' https://curl.se/
    HTTP/2 200

    http_version reports the protocol actually used, so HTTP/2 200 confirms both the negotiated transport and the successful response in a script-friendly format.

  4. Ask a cleartext HTTP endpoint to upgrade to HTTP/2 when testing h2c support.
    $ curl --http2 --silent --show-error --head http://nghttp2.org/httpbin/get
    HTTP/1.1 101 Switching Protocols
    Connection: Upgrade
    Upgrade: h2c
    
    HTTP/2 200
    date: Wed, 22 Apr 2026 03:54:05 GMT
    content-type: application/json
    content-length: 150
    ##### snipped #####

    The initial 101 Switching Protocols response is the HTTP/1.1 upgrade handshake, and the second block is the real HTTP/2 response.

  5. Skip the Upgrade: round trip only when the target is already known to accept direct HTTP/2 on cleartext HTTP.
    $ curl --http2-prior-knowledge --silent --show-error --head http://nghttp2.org/httpbin/get
    HTTP/2 200
    date: Wed, 22 Apr 2026 03:54:14 GMT
    content-type: application/json
    content-length: 150
    ##### snipped #####

    Use --http2-prior-knowledge only with controlled targets. On HTTPS, it still negotiates through ALPN, and since cURL 8.10.0 it offers only HTTP/2 instead of both HTTP/2 and HTTP/1.1.

  6. Inspect verbose output when you need proof of the ALPN decision and the final request framing.
    $ curl --http2 --verbose --silent --show-error --output /dev/null https://curl.se/
    * Host curl.se:443 was resolved.
    * IPv4: 151.101.65.91, 151.101.193.91, 151.101.1.91, 151.101.129.91
    *   Trying 151.101.65.91:443...
    * Connected to curl.se (151.101.65.91) port 443
    * ALPN: curl offers h2,http/1.1
    ##### snipped #####
    * ALPN: server accepted h2
    * using HTTP/2
    * [HTTP/2] [1] OPENED stream for https://curl.se/
    * [HTTP/2] [1] [:method: GET]
    * [HTTP/2] [1] [:scheme: https]
    * [HTTP/2] [1] [:authority: curl.se]
    * [HTTP/2] [1] [:path: /]
    > GET / HTTP/2
    < HTTP/2 200

    The ALPN lines plus using HTTP/2 and GET / HTTP/2 are stronger transport proof than the status line alone when the protocol choice must be documented.