# โก Serve HTTP/3
HTTP/3 is enabled by default: an HTTPS site uses a QUIC listener on UDP 443 unless
the global protocol list excludes `h3`. Check the response protocol: a client
may use HTTP/2 after an HTTP/3 connection fails.
๐ This page describes **v0.2.2**.
## ๐งพ Before you start
- A name that resolves to the host, and a certificate for it
([HTTPS](/start/https/)).
- **UDP 443 open** in the provider's firewall and the host's. If UDP is
blocked, clients may use HTTP/2 instead.
- A client with HTTP/3 support. The system `curl` on most distributions does not
have it and reports this error:
```text
curl: option --http3: the installed libcurl version doesn't support this
```
## ๐ Configure HTTP/3
```caddyfile
{
email bonjour@pingclair.com
servers {
protocols h1 h2 h3
}
}
example.com {
file_server /srv/site
}
```
After starting the site, check the UDP listener on the host:
```bash
sudo ss -lunp | grep ':443 '
```
```text
UNCONN 0 0 *:443 *:* users:(("pingclair",pid=5425,fd=22))
```
Removing `h3` from the list removes the QUIC listener
([TLS: what you can tune](/guides/tls-tuning/#-which-protocols-are-served)).
Without a `protocols` line, HTTP/3 remains enabled.
The `tls` block also accepts a per-site switch:
```caddyfile
example.com {
tls {
http3 off
}
file_server /srv/site
}
```
`http3 off` refuses this site's QUIC handshake and removes its HTTP/3 advertisement from `Alt-Svc`. Other sites on the port may continue to use QUIC.
## โ
Verify the client protocol
Use an HTTP/3-capable client, such as curl built with ngtcp2 or quiche. If the
host's curl lacks HTTP/3 support, use a container:
```bash
docker run --rm --network host \
ymuski/curl-http3 curl -sI --http3 https://example.com/
```
```text
curl 8.2.1-DEV (x86_64-pc-linux-gnu) libcurl/8.2.1-DEV BoringSSL zlib/1.2.13 nghttp2/1.52.0 quiche/0.18.0
```
`--network host` lets the container use the host's network directly. Without
it, the request may pass through a network namespace that blocks QUIC.
```text
HTTP/3 200
content-type: text/html; charset=utf-8
etag: "5e-6ab20622"
accept-ranges: bytes
x-served-by: pingclair
server: Pingclair
```
The `HTTP/3` status line confirms the protocol used for this response.
Requesting the same URL with `--http2` and `--http1.1` shows the other two
protocols, which confirms that the client is not falling back.
When a container is not available, a QUIC handshake can be checked with the
system's OpenSSL, if it is 3.5 or newer:
```bash
openssl s_client -quic -alpn h3 -connect example.com:443 -servername example.com
## โ ๏ธ Troubleshooting
- **`option --http3: the installed libcurl version doesn't support this`.** The
client has no HTTP/3; use a container as above.
- **`curl --http3` does not complete or times out.** UDP 443 may be blocked. Check the
provider's firewall or security group first, then the host's.
- **No UDP listener on the host.** `h3` is missing from the `servers` protocol
list, or the file that is running is not the one you edited
([what a reload means](/start/service/#-what-a-reload-means)).
- **HTTP/3 works locally and not from outside.** The client's network may block UDP
443; browsers may use HTTP/2 instead.
## ๐งญ Next steps
- [TLS: what you can tune](/guides/tls-tuning/): the protocol list, certificates,
and client certificates.
- [Project status](/project/status/): what is supported, refused, and affected by known
defects in this release.
- [`tls`](/reference/directives/#tls): the `http3` option in context.