User-Agent Client Hints vs User-Agent Sniffing
Traditional user-agent sniffing has long been a fragile, error-prone method for detecting browser and device capabilities, often leading to broken web experiences and privacy risks. The User-Agent Client Hints (UA-CH) API replaces this legacy approach by offering a structured, privacy-preserving, and deliberate mechanism for servers to request only the specific client information they need. This article explores the shortcomings of legacy user-agent strings, the architecture of User-Agent Client Hints, and how modern web developers can implement them for reliable content negotiation.
The Problem with Legacy User-Agent Sniffing
For decades, browsers communicated their identity through the
User-Agent HTTP header. Over time, this single string
accumulated historical baggage, with browsers spoofing each other's
tokens to bypass arbitrary site blocking. The result was a bloated,
unstructured string filled with conflicting identifiers (such as Chrome
reporting itself as Safari, Mozilla, and KHTML).
Parsing these strings required complex regular expressions and
constantly updated third-party detection libraries. Minor browser
updates could alter string formatting, inadvertently breaking site
functionality. Crucially, the legacy User-Agent string
broadcasted granular system details on every single HTTP request—such as
precise operating system builds and device models—making it a primary
vector for passive browser fingerprinting.
How User-Agent Client Hints Work
To resolve these issues, major browser vendors began freezing the
legacy User-Agent string and introduced User-Agent Client
Hints. Rather than sending a monolithic string by default, the browser
splits information into two categories: Low-Entropy and
High-Entropy hints.
- Low-Entropy Hints: Safe, basic information sent
automatically with every request. These do not reveal enough detail to
uniquely identify a user.
Sec-CH-UA: The browser brand and significant version (e.g.,"Chromium";v="124","Google Chrome";v="124").Sec-CH-UA-Mobile: A boolean value indicating whether the browser is running on a mobile device (?0or?1).Sec-CH-UA-Platform: The operating system family (e.g.,"Windows"or"Android").
- High-Entropy Hints: Granular details that could contribute to user tracking, such as exact OS versions, device models, full architecture, or bitness. These are never sent by default.
The Explicit Request Model
The core architectural change in UA-CH is that servers must explicitly opt in to receive high-entropy data. This shift eliminates passive tracking and forces applications to request only what is functional for their use case.
When a server requires high-entropy details, it sends an
Accept-CH response header specifying the exact hints it
needs:
Accept-CH: Sec-CH-UA-Platform-Version, Sec-CH-UA-Model, Sec-CH-UA-Arch
On subsequent requests to that origin, the browser includes the requested headers:
Sec-CH-UA-Platform-Version: "15.0.0"
Sec-CH-UA-Model: "Pixel 8"
Sec-CH-UA-Arch: "arm"
Accessing Client Hints via JavaScript
Client-side code can access low-entropy hints synchronously through
the navigator.userAgentData property, avoiding string
parsing entirely:
const { brands, mobile, platform } = navigator.userAgentData;
if (mobile) {
// Apply mobile-specific logic
}If the application requires high-entropy data, it must request it
asynchronously via getHighEntropyValues(), returning a
Promise:
navigator.userAgentData.getHighEntropyValues([
"architecture",
"model",
"platformVersion"
]).then(hints => {
console.log(hints.platformVersion);
});Why UA-CH Outperforms Legacy Sniffing
- Structured Data: Information is delivered as key-value pairs formatted according to the Structured Fields standard, removing the need for fragile regex parsing.
- Privacy by Default: By withholding detailed device identifiers until explicitly requested, UA-CH drastically limits passive tracking.
- Resilience: Because hints are explicitly typed and standardized, minor browser patches and upstream engine changes do not unexpectedly break parsing logic.
- Granular Control: Site owners and third-party
services can define permissions policies (using the
Permissions-Policyheader) to govern which subresources are permitted to access client hints.
By transitioning from passive, monolithic user-agent sniffing to targeted, structured Client Hints, modern web applications gain a more resilient codebase while respecting modern user privacy standards.