the keyboard layout maps the OEM keys the way one real Windows layout would
Check id keyboard-layout-single-origin
What an ordinary browser yields
A layout map the host produced — on Windows that means IntlBackslash is present alongside Backslash, and the key set varies with the user's actual layout rather than being the same constant everywhere.
What a detector infers
A keyboard layout is not a set of independent key mappings — it is one artifact the operating system hands over whole. On Windows it is a single layout DLL that defines the OEM keys together, and getLayoutMap() reports the glyphs that DLL produces. That gives two ways to catch a layout that was composed rather than loaded. The first is the glyph pairing: layouts that put "<"/">" on OEM_102 never put "\\" on OEM_5, so a map showing both came from no single DLL. The second is the shape of the map itself. A build cross-compiled on Linux cannot ask its host for a Windows layout, so one workaround is to ship a hardcoded US map — and a map written by hand contains exactly what a person types: the 26 letters, the 10 digits, the 11 ASCII punctuation keys, and nothing else. That 47-key set is not a shape Windows emits. Every Latin Windows layout defines VK_OEM_102, which surfaces as IntlBackslash; stock Windows Chrome was measured reporting 48 keys with IntlBackslash present. The check therefore requires the whole ASCII set, an exact size match, and the complete absence of any Intl key before it will speak, which is what separates a compile-time constant from the three real layouts that would otherwise trip it: macOS ANSI hardware genuinely has no ISO key and reports the same 47 (excluded by the Windows gate), a Japanese or Korean Windows layout may lack OEM_102 but ships IntlRo/IntlYen instead (excluded by requiring no Intl key at all), and a partial or non-Latin map is excluded by the exact-set requirement. Severity is warn: it identifies a synthesized layout, which is a strong signal about how a browser was built rather than proof of intent.
How to resolve it
Read the keyboard layout from the host instead of shipping a constant. A hardcoded map cannot vary with the user's real layout, and the specific set a person types by hand — all ASCII, no Intl keys — matches no Windows layout DLL. If the platform layout service is unavailable on the build host, leaving getLayoutMap() empty is more honest than filling it with a literal.
Read in the wild by
CloakBrowser issues
A stealth-browser tracker raises the keyboard layout as a platform-coherence surface, which is the glyph-pairing arm of this check.
CloakHQ/CloakBrowser #161 (keyboard layout vs claimed platform)
CloakHQ/CloakBrowser#161Every attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Navigator identity
- location.origin is the serialisation of its own protocol, host and port
location-origin-coherenceAn origin is not stored next to a URL, it is serialised from it: for an http or https document, origin is exactly the scheme, followed by… - navigator.vendor is the constant the measured engine compiles in
navigator-vendor-vs-enginenavigator.vendor is not a preference or a setting — it is a string constant compiled into the engine. - navigator.oscpu names the same OS family as the user-agent
ua-oscpu-os-family-coherencenavigator.oscpu is a property only Gecko still exposes — Chromium removed it and WebKit never had it — so this check is silent on every… - a worker resolves the same IANA timezone as the main thread
worker-main-timezone-coherenceA browser has one host timezone, and the specification ties both the main-thread global and every worker global to it, so a real browser… - navigator.appVersion is the user agent minus its leading token
appversion-vs-useragentnavigator.appVersion is not an independent fact. In Blink and WebKit it is computed from the User-Agent at read time — literally the UA with… - Trusted Types hands back the branded object its own type demands
trusted-types-value-invariantTrusted Types is a typed API, not a boolean feature flag, and that is the whole of the check. - the user agent on the wire and the one JavaScript reports describe the same browser
ua-wire-vs-navigatorYour user agent is asserted on two channels built by different layers: the network stack writes the header, and the renderer answers… - a Date's own text agrees with the Date's own offset
date-tostring-coherenceA Date's text is not opaque. ECMA-262 defines toString() as toDateString() + " " + toTimeString(), fixes the weekday and month tables to…
Clearcote is a browser built for fingerprint coherence
It is a Chromium fork, maintained by the same people who wrote this reference. It ships as a compiled browser rather than as a stealth script injected into someone else's — which is a description of how it is built, and is not an argument about how it behaves on this check.
This audit takes no position on how Clearcote scores on Navigator identity checks, on this one, or anywhere else. It has no baseline corpus of other people's fingerprints to rank you against and no vendor scoreboard — nearly every check is self-referential, asking one browser the same question through two independent APIs and reporting whether both answers can be true at once. It runs identically on any browser, including ours. Run it on yours and read the result yourself.
See the other checks in Navigator identity — the family keyboard-layout-single-origin belongs to.