Skip to content

Speed

HTTP/2 and HTTP/3 — what they change and how to turn them on

HTTP/1.1 loads six files at a time and queues the rest. HTTP/2 sends them all over one connection; HTTP/3 removes the slow handshake. This guide tests which one your site negotiates and shows the one-line change on each host, server and CDN.

getReport teamUpdated 25 Sept 20267 min read

A page with 80 files over HTTP/1.1 downloads them in batches of six per host, each batch waiting for the previous one. HTTP/2 sends all of them at once over one connection and compresses the headers; HTTP/3 does the same over QUIC, with a shorter handshake and better behaviour on mobile networks that lose packets. On most hosts and every major CDN, enabling them is a checkbox. This guide tests what your site negotiates, explains what the result means and gives the setting for each server.

Quick answer

  • Run the HTTP/2 test. The ALPN row says what the server chose: h2 is HTTP/2; http/1.1 means it is off.
  • nginx: listen 443 ssl; http2 on; (1.25+) or listen 443 ssl http2; on older versions.
  • Apache: a2enmod http2 and Protocols h2 http/1.1 in the virtual host; needs the event MPM.
  • Caddy: on by default, HTTP/3 too.
  • Cloudflare, Netlify, Vercel, most managed hosts: already on; HTTP/3 is a toggle in Cloudflare's Network tab.
  • Everything needs HTTPS: browsers only speak HTTP/2 and HTTP/3 over TLS.

Why HTTP/2 and HTTP/3 matter

HTTP/1.1 uses one request per connection at a time, and browsers open at most six connections per host. Everything else queues. Sites used to work around that with sprites, domain sharding and inlining; HTTP/2 makes those tricks unnecessary by multiplexing every request over one connection, prioritising them, and compressing headers (which matters when every request carries cookies).

HTTP/3 keeps the multiplexing but replaces TCP with QUIC on UDP. Two things improve: the connection sets up in one round trip instead of two or three (TLS is built in), and a lost packet only stalls the stream it belonged to, not all of them. On a good wired connection the difference is small; on a phone on the move it is visible.

Both are all-or-nothing per connection, which is why third-party files still on HTTP/1.1 show up in the per-file table: a font host or a chat widget on http/1.1 adds a connection with the old limits.

How getReport checks it

The test has two parts. First, a TLS handshake with your server that offers h2 and http/1.1 through ALPN (the extension browsers use to agree on a protocol) and records which one the server picks, plus the TLS version and cipher. The page response's Alt-Svc header says whether HTTP/3 is advertised:

Then the page is loaded in Chromium and every response is grouped by the protocol it actually used, so third-party files are covered too:

Protocol details table: HTTP/2 negotiated h2, HTTP/3 not advertised, Alt-Svc header empty, TLS 1.3 with the cipher, and a chip per protocol counting the responses from the Chromium run
The ALPN result of the handshake, the Alt-Svc header and the responses per protocol from the browser run.

Compression, cache headers and CDN detection are in the same panel because they live in the same configuration.

Step by step

1. Read the ALPN row

  • negotiated h2: HTTP/2 is on for your origin. Move to step 3.
  • server chose http/1.1: HTTP/2 is off. Step 2.
  • not tested (plain http): the page is served over http://. Move to HTTPS first; there is no HTTP/2 without it. See Security headers from zero for the redirect.
  • could not test: the handshake failed (a firewall, an odd port). Check the SSL/TLS findings.

2. Turn on HTTP/2 at the server

nginx (1.25.1 and newer):

nginx
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com;
    # certificates …
}

Older nginx: listen 443 ssl http2;. Reload with nginx -t && systemctl reload nginx.

Apache 2.4.17+: enable the module and the event MPM (prefork does not support HTTP/2 well):

Shell
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event http2
sudo systemctl restart apache2

Then in the virtual host:

Apache
<VirtualHost *:443>
    Protocols h2 http/1.1
    # …
</VirtualHost>

PHP under Apache then runs as PHP-FPM instead of mod_php; most distributions handle that with a2enconf php8.3-fpm.

Caddy: nothing to do; HTTP/1.1, HTTP/2 and HTTP/3 are on by default with automatic certificates.

Managed hosting: look for "HTTP/2" in the hosting panel; on cPanel it depends on the server's Apache build, and the host's support can confirm. Or put Cloudflare in front, which terminates HTTP/2 and HTTP/3 regardless of the origin.

3. Turn on HTTP/3

Cloudflare: dashboard → Network → HTTP/3 (with QUIC) → on. It also enables 0-RTT.

nginx 1.25+ built with QUIC:

nginx
server {
    listen 443 quic reuseport;
    listen 443 ssl;
    http2 on;
    http3 on;
    add_header Alt-Svc 'h3=":443"; ma=86400' always;
    ssl_early_data on;
}

And open UDP 443 in the firewall: ufw allow 443/udp.

Caddy: on by default; the firewall needs UDP 443.

Apache: no stable HTTP/3 support as of this writing; use a CDN or a reverse proxy in front.

4. Check the per-file table

The "Responses by protocol" chips count what the browser actually used. http/1.1: 12 on a site that negotiates h2 means those twelve files came from somewhere else: a font host, an analytics script, an image CDN on a plan without HTTP/2. Open the http2 finding to see the URLs. Replace the host, self-host the file (fonts especially), or accept it if it is one small file.

What HTTP/2 changes in how you build

Some HTTP/1.1 habits hurt on HTTP/2:

  • Domain sharding (img1., img2.) forces extra connections; consolidate to one host.
  • Sprites and inlining save requests that no longer cost much; separate cacheable files are better.
  • Bundling everything into one 2 MB JavaScript file means one change invalidates the whole cache; smaller bundles are fine now.

And one thing stays true: fewer bytes is still faster than fewer requests. HTTP/2 does not make a 1.8 MB image smaller. See Image sizes that do not hurt.

Verify

  • The ALPN row reads "negotiated h2"; the Alt-Svc row shows h3=":443" if you enabled HTTP/3.
  • The http2 finding reports the document over h2 (or h3) and few or no HTTP/1.1 responses.
  • In the browser's dev tools → Network, add the Protocol column: h2 or h3 on your files.
  • HTTP/3 needs one visit to be advertised and a second visit to be used; browsers cache the Alt-Svc hint.

Common mistakes

  • Enabling HTTP/2 on port 80. Browsers ignore it; only the TLS port counts.
  • Apache with prefork. Protocols h2 is accepted but silently downgraded; switch to the event MPM.
  • UDP 443 closed. HTTP/3 is advertised, the browser tries QUIC, times out and falls back. Slower than not advertising it.
  • A proxy in the middle. Varnish or an old load balancer speaks HTTP/1.1 to the origin; that is fine, as long as the edge that talks to browsers speaks h2.
  • Expecting a big score jump. HTTP/2 helps pages with many files; a page with one large image and one large script gains little. Fix the bytes too.
Check your site before and after Check