Resources

How do Browser and Website Negotiate Which HTTP Version is Used?

HTTP version selection is not a single handshake. It is a layered discovery and fallback process, and the result differs between a first visit and a repeat visit.

A browser connecting to a website must make two decisions that are more independent than they appear: first, whether to use TCP or UDP as the transport; and second, which HTTP version to run on top of that transport. The two decisions interact in a way that requires three separate mechanisms to resolve fully.

1. The Three Discovery and Negotiation Mechanisms

The full protocol selection process involves three mechanisms, each solving a different part of the problem.

Mechanism What it does When it applies
TLS ALPN Negotiates the application protocol during the TLS handshake Every TLS connection — determines H1 vs H2
Alt-Svc Tells the browser that an alternative service (H3) is available, via a response header After a successful HTTP response — enables H3 on the next connection
DNS HTTPS record Advertises supported protocols and ports before any connection is opened Before the first packet — enables H3 on the first connection

The reason all three are needed comes down to a fundamental constraint: TCP and UDP are mutually exclusive transports for a given connection.

HTTP/1.1 and HTTP/2 run over TCP. HTTP/3 runs over QUIC, which uses UDP. Once a browser opens a TCP connection to a server, it cannot negotiate its way onto QUIC on that same connection. ALPN can only select among protocols that run on the transport already chosen. A client that starts with TCP can negotiate H1 or H2 via ALPN, but it has no way to reach H3 from there.

This is the gap that Alt-Svc and DNS HTTPS records fill. Both are mechanisms for a client to learn, independently of the current TCP connection, that the server also speaks H3 on a UDP port.

2. TLS/TCP ALPN: Choosing H1 or H2 on a TCP/TLS Connection

ALPN (Application-Layer Protocol Negotiation, RFC 7301) is a TLS extension that lets the client and server agree on which application protocol to run, during the TLS handshake itself, before any HTTP traffic is exchanged.

The client includes a list of protocol identifiers in its TLS ClientHello:

ALPN: h2, http/1.1

The server selects one token from the list and confirms it as part of the TLS handshake. The connection then uses that protocol. If no ALPN extension is used, HTTPS clients traditionally assume HTTP/1.1. If ALPN is used but no common protocol can be selected, the handshake may fail rather than silently falling back.

H3 also uses ALPN — its token is h3. But H3's TLS handshake runs inside QUIC, not over TCP. The ALPN token h3 is therefore negotiated within a QUIC connection, after the transport-level decision to use UDP has already been made. A server cannot offer h3 in a TCP TLS handshake because there is nothing on that TCP connection that can carry QUIC frames. The transport selection must come first.

In practice, a browser opening a fresh TCP connection to a server will negotiate H2 if the server offers it, and fall back to H1 otherwise. H3 is not reachable from this TCP/TLS path; it must be discovered before opening the connection, or learned from a previous HTTP response.

3. Alt-Svc: Discovering HTTP/3 After an HTTP Response

The Alt-Svc response header (RFC 7838, extended for H3) allows a server to advertise that an alternative service is available at a given protocol and port. A typical H3 advertisement looks like this:

alt-svc: h3=":443"; ma=86400

The ma value (max-age) tells the browser how long to cache this advertisement, in seconds. After receiving and caching this header, the browser may attempt a QUIC connection to that host on subsequent visits, often before opening a new TCP connection.

This is the mechanism behind the H3 upgrade path in Chrome and Firefox on hosts that have no DNS HTTPS record. The browser opens a TCP connection, negotiates H2, and receives Alt-Svc in the response. Chrome acts on it immediately: it launches a QUIC session for sub-resources within the same page load, so later fetches on the same page (including JS-initiated requests) may already use H3. Firefox caches the header and uses H3 from the next navigation. On hosts that also carry a DNS HTTPS record, Chrome can skip the TCP step entirely and connect H3 on the very first request.

Safari does not honor Alt-Svc. Its H3 support is driven exclusively by DNS HTTPS records. A host that relies solely on Alt-Svc to advertise H3 will never upgrade Safari to H3, regardless of how many responses carry the header.

The consequences for SSE gateways differ by browser. A gateway that strips Alt-Svc prevents Chrome and Firefox from discovering H3 via that path, but has no effect on Safari — Safari was not using Alt-Svc anyway. Suppressing the DNS HTTPS record is the action that removes H3 discovery for Safari.

4. DNS HTTPS Records: Discovering HTTP/3 Before Connecting

DNS HTTPS resource records (RFC 9460) are a newer mechanism that moves protocol discovery earlier in the process — before the first TCP or UDP packet is sent to the server.

When a browser resolves a hostname, it can query not just for A and AAAA address records but also for an HTTPS record. This record carries a list of supported ALPN tokens and, optionally, explicit port numbers and priority values. A typical HTTPS record for a site supporting H3, H2, and H1 looks like this in DNS zone file presentation format:

sse-testcenter.org.  IN  HTTPS  1  .  alpn="h3,h2,http/1.1"

If the browser receives this record before making a connection, it knows immediately that QUIC/H3 is available. It can attempt a QUIC connection on the first visit, without needing a prior TCP exchange to learn about Alt-Svc.

This explains the behavior observed in SSE TestCenter testing: both Safari and Chrome use DNS HTTPS records for early H3 discovery and can reach H3 on the first visit when the record is present. Safari relies on the DNS HTTPS record exclusively — it ignores Alt-Svc entirely. Chrome uses both mechanisms independently: the DNS HTTPS record for first-visit H3, and Alt-Svc as a within-page-load upgrade path on hosts where the record is absent or arrives too late. Firefox does not use DNS HTTPS records and relies on Alt-Svc only.

The HTTPS record also carries a priority field. Multiple records with different priorities let the server express a preference order — lower numbers are preferred. This is what the SSE TestCenter hostname matrix uses to indicate which protocol a host prefers.

When a gateway intercepts DNS queries and omits HTTPS records from responses, browsers lose early H3 discovery. Safari falls back to HTTP/2 or HTTP/1.1; even on the first connection there is no QUIC attempt.

A practical complication: a browser issues A/AAAA and HTTPS queries in parallel. On a slow or unreliable DNS path, the address record may arrive before the HTTPS record. The browser may then open a TCP connection before it learns that H3 was available. This is why a first visit to an H3-only host can fail and a reload succeeds — by the time of the reload, the HTTPS record has arrived and is cached.

5. The Actual Decision Flow: First Visit, Fallback, Repeat Visit

Putting the three mechanisms together, here is how a browser decides which protocol to use.

First visit, no prior DNS or Alt-Svc cache:

  1. DNS resolver returns A/AAAA records and, if supported, an HTTPS record.
  2. HTTPS record present with h3 in the ALPN list → browser attempts QUIC on the advertised port. If QUIC succeeds, H3 is used. If QUIC fails (e.g. UDP blocked), browser falls back to TCP.
  3. No HTTPS record, or HTTPS record has no h3 → browser opens a TCP connection. ALPN negotiation selects H2 or H1. Response may contain Alt-Svc.

Repeat visit with Alt-Svc cached:

  1. Browser has a cached Alt-Svc entry for this host pointing to H3.
  2. Browser attempts QUIC directly. If it succeeds, H3 is used. If QUIC fails, browser falls back to TCP and negotiates H2 or H1.
  3. A failed QUIC attempt may cause the browser to de-prioritize or temporarily ignore the cached Alt-Svc entry, so subsequent visits retry TCP until a successful H3 connection re-establishes the cache.

Browser-specific behavior explored during testing

Safari

Safari sends the HTTPS record query before the A/AAAA query. When responses arrive in the same order, Safari has the protocol information before opening any connection and uses QUIC directly on the first visit. The failure mode arises at intermediate DNS servers: a nameserver in the path can reorder the responses and deliver the A record before the HTTPS record, sometimes with a delay of tens of milliseconds between the two. When that happens:

  1. Safari receives the A record first and opens a TCP connection, negotiating H2 via ALPN.
  2. The HTTPS record arrives while or after the TCP handshake is in progress; the connection has already committed to H2.
  3. On the next reload the HTTPS record is in the local cache; Safari uses it to open QUIC directly and the connection uses H3.

Safari does not honor the Alt-Svc response header. A host that advertises H3 only via Alt-Svc — with no DNS HTTPS record — stays on H2 in Safari regardless of how many responses carry the header. The one exception is connection coalescing: if Safari already holds an active H3 session to a different hostname at the same IP address and covered by the same TLS certificate, it will reuse that session for requests to the Alt-Svc-only host.

If the DNS HTTPS record carries a non-standard port for H2 or H3, Safari connects to that port even when the URL does not specify it. This conforms to RFC 9460 §7.2, but it has security implications for SSE gateways that filter by port — see our blog post on the H3 bypass attack.

Chrome

Chrome also sends the HTTPS record query before A/AAAA, and the same intermediate-DNS reordering problem applies: if an intermediate nameserver delivers the A record first — delayed by tens of milliseconds relative to the HTTPS record — Chrome may open a TCP connection before learning that H3 is available. Chrome adds a client-side constraint that makes it especially sensitive to this delay: after the A record arrives, Chrome runs a short internal timeout (observed at 6–8 ms in testing) and aborts the outstanding HTTPS query if it has not arrived within that window. An intermediate that introduces even a small delay between the two responses is enough to consistently miss this window.

If Chrome establishes a TCP/H2 connection and the server's response includes an Alt-Svc header, Chrome acts on it within the same page load: it launches a QUIC session immediately and routes sub-resource requests and JS-initiated fetches over H3. This means H3 can appear on the "first visit" even though the initial document request went over H2.

If neither a timely HTTPS record nor an Alt-Svc header is available, Chrome has no H3 discovery signal and will not retry H3 until the DNS TTL expires. The failure is sticky: repeated reloads will not recover until a fresh DNS task delivers the HTTPS record within Chrome's timeout window. On a host where H3 is the only available protocol, a client that lost the DNS race may see a connection error on every attempt for up to the full A-record TTL — for example 300 seconds (5 minutes).

A separate scenario removes H3 discovery entirely: endpoint firewall and CASB agents commonly install per-domain resolver entries (for example via /etc/resolver on macOS) pointing to a loopback nameserver. Chrome detects a loopback nameserver and disables its internal DNS client — no HTTPS record queries are issued at all. In that environment Chrome relies on Alt-Svc only and cannot reach H3 on a cold first visit.

Chrome ignores the DNS HTTPS port SvcParam when the value differs from the URL port: the endpoint metadata is discarded and Chrome connects to the standard port regardless. This is a non-conformance with RFC 9460 §7.2. A host deployed exclusively on a non-standard port via a DNS HTTPS record is reachable from Safari but not from Chrome.

The flows above describe direct connections. A gateway in the path can alter any of these outcomes independently — suppressing HTTPS records removes first-visit H3 for both browsers; stripping Alt-Svc removes Chrome's upgrade path but has no effect on Safari.

6. Why This Matters for SSE Gateways

A Security Service Edge gateway can affect all three mechanisms independently, and each intervention has distinct, observable consequences.

DNS interception — suppressing or modifying HTTPS records

Many SSE products act as the DNS resolver for managed clients. A gateway that does not forward or synthesize HTTPS records effectively removes early H3 discovery. Browsers that rely on DNS HTTPS records (notably Safari) will not attempt QUIC on the first visit; they fall back to TCP and negotiate H2. The gateway may never see a QUIC connection from the browser at all.

Alt-Svc stripping

A gateway that terminates the browser's TLS connection and re-originates a new upstream connection will receive the server's Alt-Svc header on the upstream side. Whether that header is forwarded to the browser is a product decision. Stripping it prevents Chrome and Firefox from learning about H3, keeping the browser on H2 regardless of what the origin supports.

ALPN on the browser side vs. the server side

A terminating gateway presents its own TLS handshake to the browser and a separate one to the origin. It can offer a different ALPN set on each side. A gateway that only offers http/1.1 to the browser will keep the browser on H1 even if it connects H2 or H3 upstream itself. Conversely, a gateway may offer H2 to the browser while using H1 upstream — the browser sees a modern protocol, but the upstream connection has no multiplexing.

QUIC blocking

Corporate firewalls and some SSE products block outbound UDP traffic, or specifically block UDP port 443. This prevents all QUIC connections regardless of what DNS records or Alt-Svc headers say. Browsers detect the failure and fall back to TCP. The gateway may intentionally cause this to keep all traffic on inspectable TCP paths.

All of these effects are visible through the SSE TestCenter Hostname Matrix. The protocol widget on each page shows what actually reached the server, the peer IP identifies the connection source, and the strict per-hostname ALPN enforcement makes the gateway's upstream behavior observable directly.

For a deeper treatment of both mechanisms — complete Alt-Svc syntax, all HTTPS record service parameters, a side-by-side comparison table, and dig commands for inspecting records directly — see DNS HTTPS Records and Alt-Svc.