How Browsers and Websites Negotiate the HTTP Version
HTTP version selection is no longer a single handshake. For HTTP/1.1 and HTTP/2, a browser opens one TCP connection and TLS ALPN decides the protocol inside it. HTTP/3 adds a decision in front of that: whether to try QUIC over UDP at all, made before any TLS handshake begins, using DNS HTTPS records, cached Alt-Svc headers, and browser-specific connection racing.
This article stays at that decision-flow level, from the perspective of SSE and Secure Web Gateway testing. The examples are based on observations made with SSE TestCenter in mid-2026; browser behavior in this area is still moving quickly, so read them as measured behavior at a point in time, not as permanent vendor guarantees — section 2 explains why.
1. Transport Selection Precedes Protocol Selection
If every connection ran over TCP, this would be a short article. TLS's ALPN extension (RFC 7301) lets the client and server agree on HTTP/1.1 or HTTP/2 during the handshake itself, and that is the entire negotiation:
ALPN: h2, http/1.1
The server picks one token from the client's list and the connection uses it from then on. There is no discovery problem, no caching, and no first-visit/repeat-visit distinction — every connection negotiates fresh, in-band, in the same round trip that establishes TLS.
HTTP/3 also uses ALPN — its token is h3 — but that negotiation happens
inside a QUIC connection, and QUIC runs over UDP, not TCP. A client that has already
opened a TCP connection has nothing on that connection that can carry QUIC frames; there
is no in-band way to renegotiate onto a different transport mid-connection. So the
transport decision — TCP or UDP — has to be made before ALPN ever runs, using
information gathered outside the connection itself. That is the actual subject of this
article: not "which HTTP version," but "how does a browser decide, before opening
anything, whether to try UDP at all."
2. Scope of This Article: A Fast-Moving Target
There is no single standardized algorithm yet for how a browser should make the TCP/UDP decision. There is an emerging one — the IETF HAPPY working group's Happy Eyeballs Version 3 draft (revision -04 as of July 2026, Standards Track) — which describes racing QUIC and TCP connection attempts concurrently rather than trying one and falling back to the other, preferring QUIC when both succeed, and folding DNS SVCB/HTTPS records into the same algorithm as the source of protocol hints. That is a good description of where browsers are heading. It is not yet a description of what any one of them reliably does today.
In practice, the behavior we could observe on SSE TestCenter varies by browser vendor,
by version within the same vendor, by operating system running the identical browser
version, and by feature flags a user or a device-management policy can set — sometimes
all at once. The /etc/resolver story in the Chrome
section below is a direct illustration: the identical Chrome build behaves
differently on two otherwise-identical machines, purely because of a local DNS
configuration difference. Nothing here should be read as "this is how Chrome works" so
much as "this is how Chrome worked, on this build, on this platform, in mid-2026."
Expect it to keep moving, generally in the direction the draft describes.
3. Three Discovery Mechanisms
With that caveat in place, the TCP/UDP decision today is controlled by some combination of three things:
| Mechanism | What it does | When it applies |
|---|---|---|
| DNS HTTPS record | Advertises supported protocols, and optionally ports, before any connection is opened | Before the first packet — can enable H3 on the first connection |
| Alt-Svc | Tells the browser an alternative service (H3) is available, via a response header on an already-open connection | After a successful HTTP response — enables H3 on a later connection, or in Chrome's case, on later requests within the same page load |
| Direct probing | The browser attempts a QUIC connection alongside, or instead of, a TCP one, and keeps whichever completes first | Usually triggered by one of the two signals above; on some platforms and in some experimental configurations, browsers are starting to try QUIC with no prior signal at all |
The first two are advertisements the server makes; the third is what the browser actually does in response, which is where Happy Eyeballs-style racing comes in. Section 4 introduces Alt-Svc and DNS HTTPS records; the racing behavior itself shows up throughout the per-browser notes in section 5, since it is currently the least standardized of the three.
A separate axis compounds the matrix: browsers race IP address families the same way they are starting to race transports. Given both an IPv4 and an IPv6 address, current Happy Eyeballs guidance is to interleave attempts with a preference for IPv6, on the reasoning that IPv6 paths tend to be more direct and less likely to traverse NAT or carrier-grade middleboxes. Put together with the transport race, the general direction a well-connected dual-stack client is heading toward is IPv6 + H3 (QUIC) where available, falling back through IPv6+H2, IPv4+H3, and IPv4+H2 roughly in that order of preference. We have not run a dedicated IPv4/IPv6 comparison on SSE TestCenter, so take this paragraph as general Happy Eyeballs behavior rather than a site-specific measurement.
Network conditions and intermediate devices can interrupt any leg of any of these races — a dropped UDP packet, a stripped DNS record, a proxy that terminates TLS itself — without the user necessarily noticing, since the browser simply falls back to whatever transport did work. Section 6 covers what that looks like from the gateway operator's side of the same race.
4. Alt-Svc and DNS HTTPS Records
Two independent mechanisms let a server tell a browser that H3 is available, without relying on the TCP connection the browser may already be trying to open.
Alt-Svc (RFC 7838,
extended for H3) is an HTTP response header. It only reaches the browser after a
successful H1 or H2 response, so it can never help the very first connection of a
session — but a browser that caches it will attempt QUIC on a later connection, and
Chrome acts on it quickly enough to sometimes upgrade sub-resource requests within the
same page load (section 3's racing behavior again). macOS Safari does not act on
Alt-Svc at all — its H3 discovery runs through DNS HTTPS records only; see
section 5 for the platform split we found here.
DNS HTTPS records (RFC 9460)
move the same kind of information into DNS, queried alongside the ordinary A/AAAA
lookup, before any connection is attempted. A browser that receives one and sees
h3 in its ALPN list can attempt QUIC on the very first connection of a
session — the only way a cold first visit can reach H3 at all. This is also the
mechanism a gateway removes by omitting HTTPS records from its DNS responses: browsers
that depend on it, notably Safari, fall back to H2 or H1 with no QUIC attempt, even on
the first connection.
Both signals are cached — Alt-Svc via its ma max-age, the HTTPS record via
its DNS TTL — and both can be present, absent, or overtaken by a slower DNS response
that arrives after the browser has already committed to TCP. Section 5 covers how each
browser resolves that in practice.
SSE TestCenter exposes these combinations directly in the
Hostname Matrix. h2-h3-alt.sse-testcenter.org, for
example, serves H2 and H3 but carries no DNS HTTPS record, so it advertises H3 through
Alt-Svc alone — a useful host for isolating Alt-Svc behavior specifically,
including the macOS/iPadOS Safari split covered in section 5.
Alt-Svc header
syntax, the complete set of HTTPS record service parameters, a side-by-side comparison
table, and dig commands for inspecting records directly, see
DNS HTTPS Records and Alt-Svc.
5. Decision Flow: First Visit, Fallback, and Repeat Visit
Putting the three mechanisms together, a simplified decision flow looks like this:
h3 that arrives before the browser
commits to TCP lets it attempt QUIC immediately — the only path to H3 on a genuinely
cold first visit.Alt-Svc.Alt-Svc entry, or a DNS HTTPS record cached from an earlier
visit, lets a later connection attempt QUIC directly instead of starting over on TCP.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, Safari opens a TCP connection and negotiates H2; the HTTPS record arrives while or after the handshake, too late to change that connection's protocol; and the next reload, with the record now cached, uses QUIC directly.
macOS Safari
macOS 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
macOS 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, covered by the same TLS certificate, it may reuse that
session for the new host without ever consulting Alt-Svc for it. See our
DNS HTTPS Records and Alt-Svc page for
the detailed coalescing example.
If the DNS HTTPS record carries a non-standard port for H2 or H3, macOS Safari connects to that port even when the URL does not specify it — conformant with RFC 9460 §7.2. Safari's recovery from a lost DNS race also appears faster than Chrome's: rather than waiting out the full A-record TTL, a reload typically recovers within a much shorter window, though the exact retry mechanism is not fully characterized.
iPadOS Safari
Cross-device testing found that iPadOS Safari genuinely differs from macOS Safari here —
it does honor Alt-Svc. A controlled test (two physical devices, same
network, the iPad with zero prior session state for the host under test — ruling out
connection coalescing as an explanation) showed the classic Alt-Svc signature: the first
request went out over H2 carrying no prior knowledge, the H2 response included
alt-svc: h3=":443", and the very next connection attempt opened a fresh
QUIC session and completed over H3. The likely underlying cause is a newer network
loader Apple is rolling out unevenly across platforms — the kind of cross-version,
cross-OS drift this whole article warns about in section 2. Any third-party iPad/iPhone
browser built on WKWebView, which is mandatory for App Store apps, inherits this same
behavior, since it shares Safari's network stack.
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. We
confirmed this directly: two otherwise-identical Macs on the same network, running the
identical Chrome version, showed opposite behavior — one issuing HTTPS queries, the
other not — and the only configuration difference was a set of /etc/resolver
entries with a loopback nameserver added for endpoint firewall testing on the second
machine. Removing those entries and restarting Chrome restored the HTTPS queries
immediately. 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. (Chrome behaves differently again when the URL itself contains an
explicit non-standard port — see our
DNS HTTPS Records and Alt-Svc page for
that case, including a resolver-dependent Chrome bug we ran into and reported upstream.)
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 macOS 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/UDP blocking — what it actually costs
A common enterprise control is blocking outbound UDP/443, which prevents QUIC while
leaving TCP/443 (H2, H1) intact. Because Chrome races a QUIC attempt and a TCP attempt
concurrently whenever a DNS HTTPS record advertises h3 (section 3), blocked
UDP packets are simply dropped in the background while the TCP/H2 handshake completes
normally. In our testing this produced no perceptible delay for
dual-stack hosts (H2+H3 on the same port): the TCP job typically completed in
100–200 ms while the QUIC job was still retransmitting, and was cancelled once TCP
won.
The one case where blocking UDP/443 is not free is an H3-only host: there is no TCP fallback to race against, so the browser has to wait out QUIC's retransmission timeline in full — retries at roughly 300 ms, 600 ms, and 1200 ms after the initial attempt, then an idle-timeout failure around 4 seconds. That is the only scenario in which a UDP block produces a user-visible stall, and it reinforces the general point made throughout this article: an H3-only host is a poor choice for a production service, precisely because it removes the TCP fallback that makes every other part of this negotiation forgiving of a blocked or missing signal.
Blocking UDP/443 is consequently a low-impact way to force inspectable TCP traffic for the vast majority of real deployments. Pairing it with Alt-Svc stripping and DNS HTTPS suppression is defense in depth — not required to avoid user-visible delay, but it stops browsers from attempting QUIC on the wire at all, and closes the path by which a client could fall back to a cached H3 entry from before the block was put in place.
No single control is sufficient on its own: DNS HTTPS suppression prevents first-visit H3, Alt-Svc stripping prevents learned H3, and UDP blocking prevents QUIC even when a browser already holds a cached H3 entry from before any control was in place. Which combination is necessary depends on the gateway's architecture and whether it terminates TLS.
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.