Using HTTP/3 with cURL is a direct way to confirm that an HTTPS endpoint can complete a request over QUIC before monitoring, edge routing, or client policy starts depending on that transport.
The --http3 option tells cURL to start with HTTP/3 and then fall back to HTTP/2 or HTTP/1.1 if the QUIC path does not come up quickly enough, while --http3-only removes that fallback and makes the request fail when HTTP/3 cannot be established. Both options require a cURL build whose Features: line includes HTTP3.
Packaged cURL builds do not all include QUIC support, and network devices can still block or delay UDP even when ordinary HTTPS works over TCP. Check the local build first, use --http3 to prove negotiated transport, and reserve --http3-only for strict checks where a timeout or connection failure is acceptable.
Related: How to use HTTP/2 in cURL
Related: How to debug HTTP requests with cURL
$ curl --version curl 8.19.0 (aarch64-apple-darwin25.3.0) libcurl/8.19.0 OpenSSL/3.6.2 zlib/1.2.12 brotli/1.2.0 zstd/1.5.7 nghttp2/1.69.0 ngtcp2/1.22.1 nghttp3/1.15.0 Release-Date: 2026-03-11 Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt mqtts pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile libz SSL threadsafe UnixSockets zstd
Look for HTTP3 in the Features: line. Without it, --http3 and --http3-only fail immediately with an unsupported-option error.
$ curl --http3 --silent --show-error --head https://portal-edge.example.test/ HTTP/3 200 content-length: 18426 server: edge-proxy content-type: text/html; charset=utf-8 cache-control: max-age=60 alt-svc: h3=":443"; ma=86400
A status line that starts with HTTP/3 confirms that the transfer completed over QUIC instead of a TCP fallback.
Related: How to send HEAD requests with cURL
$ curl --http3 --silent --show-error --output /dev/null --write-out '%{http_version}\n' https://portal-edge.example.test/
3
Output 3 confirms successful HTTP/3 negotiation, while 2 or 1.1 shows that the request finished over an earlier HTTP version instead.
$ curl --http3 --verbose --silent --show-error --output /dev/null https://portal-edge.example.test/ * Host portal-edge.example.test:443 was resolved. * IPv4: 192.0.2.24, 192.0.2.25 * Trying 192.0.2.24:443... ##### snipped ##### * using HTTP/3 * [HTTP/3] [0] OPENED stream for https://portal-edge.example.test/ * [HTTP/3] [0] [:method: GET] * [HTTP/3] [0] [:authority: portal-edge.example.test] > GET / HTTP/3 < HTTP/3 200
The using HTTP/3 line and the HTTP/3 stream metadata provide stronger transport proof than the response status line alone.
$ curl --http3 --silent --show-error --output /dev/null --write-out '%{http_version}\n' https://legacy-www.example.test/
2
An output such as 2 or 1.1 means the request still succeeded, but the transfer did not stay on HTTP/3.
$ curl --http3-only --silent --show-error --head https://portal-edge.example.test/ HTTP/3 200 content-length: 18426 server: edge-proxy content-type: text/html; charset=utf-8 cache-control: max-age=60 alt-svc: h3=":443"; ma=86400
Strict mode is appropriate when fallback would hide a broken QUIC path that should fail a check instead.
$ curl --http3-only --max-time 5 --silent --show-error --head https://legacy-www.example.test/ curl: (28) Connection timed out after 5001 milliseconds
--http3-only does not downgrade to HTTP/2 or HTTP/1.1, so unsupported targets and UDP-blocked paths fail the transfer instead of silently succeeding over TCP.