Chrome's --user-agent flag changes the User-Agent string and leaves the client hints half-done, so on its own it is a fingerprint rather than a disguise. We measured exactly that, and then found something worse: whether our launcher sent the flag at all depended on a cache that was empty at every app start. The first profile launched in each session wore one identity, and every later launch of the same profile wore another.
Two runs, two browsers
The report was a Pixelscan screenshot: "Your Browser Fingerprint is inconsistent", with the browser card red and reading Edge 153.0.8010.37 on Windows. A second run of the same profile read Edge 153.0.0.0. One profile, two answers, which is how every report that arrives as "sometimes" looks.
We read the headers off a local server, launching the same Edge profile twice:
without --user-agent UA Edg/153.0.8010.37 Sec-CH-UA-Bitness "64"
with --user-agent UA Edg/153.0.0.0 Sec-CH-UA-Bitness ""
Neither row is a real browser. User-Agent reduction pins everything after the major version to zero, so no Edge release has put a build number in its User-Agent. And no browser sends an empty Sec-CH-UA-Bitness beside a filled-in Sec-CH-UA-Arch. That empty value is Chromium declining to vouch for high-entropy hints it cannot derive from a User-Agent it did not build.
So the two choices on offer were a wrong User-Agent or a wrong bitness hint.
Every profile is drawn from one real computer, not from separate listsIn Mosaic: Machines that exist. GPU, screen, CPU and fonts from one real device. Free holds 3 profiles. Pro is $49 a month for any number.
Mosaic is a desktop app
Email yourself the link and open it on your computer.
How it works: Machines that exist
What --user-agent does and does not move
If you launch Chrome with --user-agent="...", the User-Agent header and navigator.userAgent change. Everything else that describes the same browser stays where it was or goes blank: the brand list in navigator.userAgentData, the Sec-CH-UA headers, and the high-entropy hints a site asks for, such as platform version, architecture and bitness.
A site that compares those does not need to know the real value. It needs two answers that disagree, and the flag supplies them. That is the general problem with changing a fingerprint from outside the engine, whether by flag or by page script, which we wrote about in C++, not JavaScript.
Why it was intermittent
Our launcher passed --user-agent only when the profile's string differed from the engine's own. The engine's own came from an in-memory Map, filled on first use and empty at every app start. Measured on one profile, three launches after restarting Mosaic:
launch 1 Edg/153.0.8010.37
launch 2 Edg/153.0.0.0
launch 3 Edg/153.0.0.0
The first launch found the cache empty and skipped the flag. Every later launch found it full and sent it. A profile that presents two identities is worse than either one, because a real browser does not change its build number between two visits on the same day.
We now state the rule plainly in our own notes: a flag whose presence depends on a cache is a fingerprint that depends on launch order.
One switch meaning two things
Underneath the cache was the real cause. Our engine takes a --fingerprint-brand-version switch, and it meant two things. It was the only source for the client-hint version lists, which need the full build, 153.0.8010.37. And the code that builds the Edge suffix used the same value verbatim in the User-Agent, which needs 153.0.0.0.
The patch already knew both shapes. It carried the reduced version for Edge's User-Agent and used it, but only when the switch was absent. Supplying the switch, which we must for the hints, took the other path.
Chrome never showed the fault because Chrome has no suffix. For a Chrome profile, the engine builds the User-Agent byte for byte from the platform the profile claims, with no --user-agent at all. Measured on a fresh Windows Chrome profile, three launches from a cold start: the User-Agent matched the stored string every time, and Sec-CH-UA-Bitness was "64" every time.
What we changed
Edge is refused. It had been drawn for 14% of Windows profiles; now none are, and asking for it by name gets an error that quotes both measurements rather than a bare list of allowed brands. A check in our build, check:brand, keeps it that way.
The patch is fixed for later engine builds: a build number is cut down to the reduced form before it reaches the suffix, so one switch can serve both shapes. Edge stays refused until an engine built from that fix has been measured.
The Pixelscan report also said "No proxy detected", because the run came from a home address. That half was not a bug. Half of what a consistency scanner checks is whether the exit agrees with the timezone and language, so a profile measured without its proxy is being graded on the wrong address.

How the browser identity itself is drawn, from real hardware records rather than typed strings, is on real fingerprints. The control we now run first, before blaming our own engine for any verdict, is in the control that settles "is it our patches?".



