Client Hints Are Replacing User-Agent — What That Means for Tracking
TL;DR. Chromium is in the middle of a multi-year project to freeze theUser-Agent string and move browser identity into a structured family of Sec-CH-UA-* request headers (and a matching navigator.userAgentData JS API). The goal is less passive fingerprinting; the result is a more granular control surface that legitimate operators can opt into and trackers are already adapting to. Firefox and Safari have said they will not ship the new headers — so the old User-Agent is going to be around for a long time.
Why User-Agent had to go
The User-Agent header has been an honest accident for thirty years. It was meant to identify the user's browser, ostensibly so servers could send appropriate content. Within a few years it had accreted a Mozilla compatibility token, a Gecko-like compatibility token, a Safari compatibility token, and an arms race of fake brands competing to look like Netscape. By 2020 the average User-Agent was a 90-byte string conveying maybe 5 bytes of useful information, and crucially: that string was readable by every script on the page and contained enough joint entropy (OS version + browser version + platform + GPU vendor on some browsers) to uniquely identify a device.
Chromium's User-Agent Reduction project replaces all of that with two things: a frozen string that conveys only the high-level browser family (“Chrome 126, Windows”), and a set of request headers that servers can opt into when they need more. Each header reveals one thing and one thing only — your OS, your platform version, your CPU architecture, your model — and sensitive ones require user-gesture-driven permission. The story Google tells is that this turns a passive fingerprint surface into an active one a privacy-conscious server can avoid.
The new vocabulary
Always-on (low-entropy)
Sec-CH-UA— browser brand list (with a GREASE entry to discourage parsing-based blocking).Sec-CH-UA-Mobile— boolean (?1/?0).Sec-CH-UA-Platform— OS family (“macOS”, “Windows”, “Android”…).
High-entropy (Accept-CH opt-in)
Sec-CH-UA-Platform-VersionSec-CH-UA-ArchSec-CH-UA-BitnessSec-CH-UA-Model(device-identifying; requires user gesture)Sec-CH-UA-Full-Version-List— full version of every brand in the list.
Servers opt in by sending an Accept-CH response header listing the hints they want; the browser then includes them on subsequent same-origin navigations. Critical-CH can force an immediate retry if a hint matters for the first response.
Old shape vs new shape, same browser
Same browser, two completely different shapes on the wire. Pick a client to compare what a server used to receive against the structured headers Chromium emits today.
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36Sec-CH-UAlow"Chromium";v="126", "Not.A/Brand";v="24", "Google Chrome";v="126"Sec-CH-UA-Mobilelow?0Sec-CH-UA-Platformlow"macOS"Sec-CH-UA-Platform-Versionmedium"14.5.0"Sec-CH-UA-Archmedium"arm"Sec-CH-UA-Bitnessmedium"64"Sec-CH-UA-Modelhigh""Sec-CH-UA-Full-Version-Listmedium"Chromium";v="126.0.6478.127", "Google Chrome";v="126.0.6478.127", "Not.A/Brand";v="24.0.0.0"Accept-CH opt-in from the server (and in some cases a user permission prompt).What your browser actually sends right now
The widget below is live: it reads your current browser's User-Agent string and queries navigator.userAgentData for the low- and high-entropy hints in one shot. If you are on Firefox or Safari, the right-hand column will be empty — those browsers have signalled they will not implement the JS API or the headers.
Left column: the legacy User-Agent header. Right column: the new Sec-CH-UA-* client hints, read here via the navigator.userAgentData JS API.
loading…Note: only the low-entropy hints (Sec-CH-UA,Sec-CH-UA-Mobile,Sec-CH-UA-Platform) are sent by default. Servers must opt in to the high-entropy ones via the Accept-CH response header, and Chromium will ask the user for permission for the most sensitive ones likeSec-CH-UA-Model.
What this changes for trackers
The reduction does meaningfully shrink the passive UA fingerprint. The frozen string is the same for every install of the same Chromium major version on the same OS family — there is no longer a free signal that you are on macOS 14.5 build 23F79 with an arm64 chip. Trackers who relied on parsing User-Agent in their first-party JS lost real entropy.
What they have done instead, in roughly increasing order of effort:
- Just opt into the high-entropy hints. A single
Accept-CH: Sec-CH-UA-Platform-Version, Sec-CH-UA-Arch, Sec-CH-UA-Bitness, Sec-CH-UA-Full-Version-Listrecovers most of what User-Agent used to tell them. The bargain is that servers have to explicitly ask, which makes it visible in dev tools and easier to audit. - Combine with canvas / WebGL / audio fingerprinting. The browser features used in our browser fingerprinting article are unaffected by UA reduction and routinely produce more discriminating fingerprints than UA ever did.
- Move identity into authenticated context. First-party cookies, login state, federated identity. None of this depends on User-Agent.
- Use JA4 at the TLS layer. We have a dedicated JA3/JA4 explainer — the takeaway is that Chrome 126 vs Firefox 127 already had distinct ClientHello fingerprints before HTTP started.
Net effect: trackers with a budget for engineering are fine. The casual ones — random ad networks that parsed the UA string in a regex — lost a small amount of signal, which is probably the biggest privacy win of the project.
What this means for operators
- Stop parsing User-Agent for routing decisions. The frozen string can no longer tell you the platform version. If you need it (e.g. to serve OS-specific binaries), ask for it explicitly via
Sec-CH-UA-Platform-Version. - Document your
Accept-CHpolicy. Asking for more is fine; asking for everything is a smell. Audit what you actually need. - Don't break Firefox / Safari. They will keep sending the legacy User-Agent. Your code path for parsing it has to stay until Chromium is no longer in the picture, which will never happen.
- Test with
--user-agent-reduction. Chromium ships flags for forcing the frozen UA and disabling the high-entropy hints — useful for catching regressions before the reduction reaches stable.
See what websites learn about you
Beyond UA, modern fingerprinting layers many smaller signals — canvas, fonts, audio, WebGL — that have nothing to do with HTTP headers. Our browser fingerprinting article pairs well with this one for the full picture, and IP Details shows you what the request that just hit our edge looked like to us.