How Client Hints Replace User-Agent Strings

User-Agent Client Hints (UA-CH) replace the traditional, monolithic User-Agent (UA) string with a privacy-focused, structured mechanism for sharing browser and device data. Instead of automatically broadcasting detailed system information on every HTTP request, Client Hints separate data into low-entropy (basic) and high-entropy (detailed) categories. This architecture allows web servers and JavaScript APIs to selectively request only the specific device characteristics they need, reducing passive browser fingerprinting while maintaining necessary developer functionality.

The Shift Away from the Legacy User-Agent String

The legacy User-Agent string included the browser name, rendering engine, operating system version, and device type in a single plain-text header. Because browsers broadcast this complete string with every network request, trackers could easily correlate user sessions across the web without user consent. Major browsers have responded by “freezing” or reducing the legacy UA string, populating it with generic values, and introducing User-Agent Client Hints as the standard replacement.

How Servers Read Client Hints

On the server side, data exchange moves from an all-in-one broadcast model to an explicit request-and-response negotiation:

  1. Default Low-Entropy Headers: By default, browsers send only basic, non-identifying headers with initial HTTPS requests. These typically include:

    • Sec-CH-UA: The browser brand and significant version (e.g., "Chromium";v="120").
    • Sec-CH-UA-Mobile: A boolean flag indicating if the request comes from a mobile device (?0 or ?1).
    • Sec-CH-UA-Platform: The operating system family (e.g., "Windows" or "Android").
  2. Requesting High-Entropy Headers: If a server requires deeper data (such as the exact OS version, device model, or architecture), it must explicitly request it by returning the Accept-CH response header:

    Accept-CH: Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Arch
  3. Subsequent Transmissions: Upon receiving this header over a secure HTTPS connection, the browser sends the requested high-entropy headers on subsequent requests to that origin:

    Sec-CH-UA-Model: "Pixel 7"
    Sec-CH-UA-Platform-Version: "14.0.0"
    Sec-CH-UA-Arch: "arm"

How JavaScript Reads Client Hints

On the client side, the legacy navigator.userAgent string property is replaced by the navigator.userAgentData object.

  1. Synchronous Low-Entropy Access: Developers can instantly read basic properties without performance penalties:

    const brands = navigator.userAgentData.brands;
    const isMobile = navigator.userAgentData.mobile;
    const platform = navigator.userAgentData.platform;
  2. Asynchronous High-Entropy Access: To access detailed device metrics, JavaScript must invoke the asynchronous getHighEntropyValues() method, passing an array of the required hint keys:

    navigator.userAgentData.getHighEntropyValues([
      "architecture",
      "model",
      "platformVersion",
      "fullVersionList"
    ]).then(hints => {
      console.log(hints.model);
      console.log(hints.platformVersion);
    });

Because high-entropy retrieval is asynchronous, the browser can enforce privacy budgets, evaluate permissions, or log access to sensitive hardware information before returning the data.

Summary of Advantages