Client hints were Chromium's answer to the User-Agent string. The old string packed brand, version, operating system and device into one line that every server received whether it wanted it or not. Client hints split that line into separate fields, send a small set by default, and make a site ask for the rest. For fingerprinting they did not remove information. They moved it, and added a second place where a browser can contradict itself.

How client hints work

On every request a Chromium browser sends three low-entropy hints, as MDN's client hints page describes:

Sec-CH-UA: "Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="24"
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Platform: "macOS"

A server that wants more answers with an Accept-CH header naming the hints it wants, such as Sec-CH-UA-Arch, Sec-CH-UA-Bitness, Sec-CH-UA-Platform-Version, Sec-CH-UA-Model or Sec-CH-UA-Full-Version-List, and the browser sends them on later requests. A script reads the same values through navigator.userAgentData.getHighEntropyValues() (MDN), so the server-side and page-side copies can be compared. The core hints are defined in the WICG specification. Chromium also sends preference hints such as Sec-CH-Prefers-Color-Scheme when a site asks, and they carry the dark-mode and reduced-motion settings as request headers.

The fingerprint is changed inside the engine, not painted on topIn Mosaic: Its own Chromium. Tesseract Chrome: values changed in C++, not JavaScript. Free holds 3 profiles. Pro is $49 a month for any number.

How it works: Its own Chromium

What client hints fingerprinting learns

Taken alone, the hints narrow a visitor down by brand list, full build number, operating system version, CPU architecture and, on Android, the phone model. That is useful but common: millions of people run the same Chrome on the same macOS.

The stronger use is cross-checking. A site holds four copies of the same claim: the User-Agent header, navigator.userAgent, the Sec-CH-UA headers and userAgentData. On a real Chrome all four agree, every time, in every request. A spoof that changed one of them and not the others is visible from a single page load, and no JavaScript has to run for the header half.

We have produced the contradictions ourselves while building Mosaic, which is how we know they are easy to make. Overriding the User-Agent with Chromium's --user-agent switch, even with a string byte-identical to Chrome's own, empties every high-entropy hint: architecture, bitness, platformVersion, uaFullVersion and fullVersionList all came back blank. Claiming Edge gave a profile Edg/153.0.0.0 in its User-Agent beside an empty Sec-CH-UA-Bitness and a populated Sec-CH-UA-Arch, a pair no browser sends. And before we drew dark mode and accessibility settings per profile, two unrelated profiles on one Mac both sent Sec-CH-Prefers-Reduced-Motion: reduce, copied from the host, which made them identical on a setting few people turn on.

How to check yours

Open a page that echoes request headers and one that calls getHighEntropyValues(), then compare. The brand list, the full version and the platform version should be the same in both, and should match the version in the User-Agent string. The public test pages for the rest of the fingerprint, and what each one is good at, are in check your browser fingerprint. If any high-entropy field is empty while the others are filled, something has overridden the User-Agent.

Creating a profile in Mosaic: a checked proxy, and the hardware and locale drawn to match its exit
A profile's platform and browser, drawn as one machine

How Mosaic handles it

Mosaic's engine builds the User-Agent and every client hint from the same platform claim, inside the browser, so the header, the script and the hints answer from one source. When a profile's User-Agent is the engine's own, which is the ordinary case, it launches without --user-agent, so the high-entropy hints stay filled. Profiles claim Chrome only: we refuse Edge, because the switch that sets its client-hint versions also set its User-Agent suffix, and it could have a correct User-Agent or a correct bitness, never both. Dark mode is drawn at 30% of profiles and the accessibility preferences are drawn per profile too, so the Sec-CH-Prefers-* headers do not repeat the host. Why branded Chrome and unbranded builds differ in the first place is in Chromium vs Chrome, and the same agreement test one layer down, in the TLS handshake, is TLS fingerprinting.

Sources

  1. MDN: HTTP Client hints, read November 2, 2026
  2. MDN: NavigatorUAData.getHighEntropyValues(), read November 2, 2026
  3. WICG: User-Agent Client Hints, read November 2, 2026