Skip to content
All fingerprint checksWorker realms

Every worker realm reports the same identity as the window

Check id worker-realms-agree

What an ordinary browser yields

An ordinary browser: every worker realm that answers reports byte-identical userAgent, platform, hardwareConcurrency, deviceMemory and engine id — pass, severity critical.

What a detector infers

A page is not one JavaScript realm — it is several. The audit loads one probe script into all three worker kinds the platform offers: a dedicated Worker, a SharedWorker and a ServiceWorker, raced in parallel, each reporting its own `navigator` from inside its own scope. The check then diffs four fields against the window — userAgent, platform, hardwareConcurrency, deviceMemory — plus the computed engine id (RangeError message length + Array-constructor source length), flagging any worker value that is defined and stringifies differently from the window's. The mechanism a detector relies on is simple: those values originate from the same browser process and must be identical, so a divergence cannot be a browser variation — it can only be an override installed on the main-thread `navigator` object that never followed into `WorkerNavigator`, which lives in a separate realm with a separate global. The three tiers are not redundant. Tooling that accounts for this at all usually accounts for the dedicated Worker, because that is the one everybody tests; SharedWorker and ServiceWorker are reached less often and answer honestly for longer. The ServiceWorker in particular is the realm most audits never inspect, for a mundane reason worth knowing — registration rejects blob: URLs, so any probe built the easy way structurally cannot see it. Note also what the check deliberately does NOT assert on: language and languages are excluded, because Chrome has a long-standing legitimate divergence between window and worker there, and asserting on it would fail stock, unmodified browsers. A detector that knows when not to assert is what separates a signal from noise.

How to resolve it

A spoof applied to the main-thread navigator does not propagate into WorkerNavigator. Apply the same identity in every realm, or set it at launch/browser level so no realm needs patching at all. Patching only the realms that are easy to reach is worse than patching none: it converts a value into a contradiction, which is the more legible of the two. Realms that cannot answer — SharedWorker is absent on Android Chrome and in Firefox private windows, ServiceWorker needs a secure context — are excluded rather than counted, and if no scope answers at all the check reports pass:null. One more exemption is worth knowing: a userAgent disagreement confined to the ServiceWorker tier is reported but not counted. A single ServiceWorker instance serves every client in its scope, so the browser starts it from the browser process with the build's default UA and there is nowhere to put a per-tab override — which means Android WebView's in-app browsers (Instagram, Facebook, TikTok) and Chrome for Android's Request-desktop-site structurally cannot reach it, and would otherwise convict a completely stock browser. The exemption is narrow on purpose: every other field is still asserted on that tier, and a UA disagreement that ALSO appears on the dedicated or shared tier — the shape a page-world spoof makes — still counts, because those tiers do carry the embedder's override.

Cross-realm coherence: why a worker must agree with the page

Read in the wild by

CreepJS

Runs one identical probe body in four realms — window, dedicated Worker, SharedWorker and ServiceWorker — and diffs the results.

tests/workers.html + docs/tests/worker_service.js; shipped module src/worker/index.ts

CreepJS (abrahamjuliot/creepjs)

Every attribution traces to a published artifact. See the sources and their limits.

Other checks in Worker realms

Who builds this test

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 Worker realms 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 Worker realms — the family worker-realms-agree belongs to.