Skip to content
All fingerprint checksAutomation surface

window.chrome present for a Chrome UA

Check id chrome-object

What an ordinary browser yields

A Chrome-claiming UA is accompanied by a present, truthy window.chrome; non-Chrome engines are not scored.

What a detector infers

This is a cross-check, not a probe of window.chrome's contents: it first decides whether the browser claims to be Chrome (a Chrome/ token in the user agent, or the presence of navigator.userAgentData), and only then requires that window.chrome exists and is truthy. Real Chrome always populates this object; older headless builds and stripped or minimally-shimmed environments did not, so a Chrome user agent arriving without it is two signals disagreeing about what the browser is. The N/A branch is what keeps the check honest — on a non-Chrome engine the absence of window.chrome is correct, so nothing is scored. Severity is warn rather than critical because modern headless populates the object and the tell is largely historical.

How to resolve it

Run a real Chromium build so the object is present natively, or stop claiming a Chrome UA on an engine that isn't Chrome. Hand-building a window.chrome does satisfy this check, but it only relocates the problem: as soon as such a shim also fills in chrome.csi or chrome.loadTimes in JavaScript, the native-stubs check catches those members by their toString output. An empty stand-in object clears both checks while still contradicting every other Chrome-shaped signal on the page, which is why the object's presence is scored as a warning rather than treated as proof of a real Chrome.

How is a headless browser detected?

Read in the wild by

PerimeterX / HUMAN

Reads window.chrome and ships three separate fields: the object's own key list verbatim via Object.keys, a hash of a structural walk of the object and its prototype chain, and chrome.runtime.id as its own plaintext field.

main.min.js (PerimeterX collector, ifood): `Ax=hS[jb("Y2hyb21l")]` + `function AP(){return Ax}` capture window.chrome; in AR(t): `i=AP(),i&&(t["Q3M2OQUTNAM="]=kn(ko(i)))` where ko walks the object and its prototype and kn hashes; in Ci(t): `t[hQ(749)]=...?Object[hQ(386)](hS.chrome):[]` and `t[hQ(746)]=hS.chrome&&hS[hQ(747)][hQ(748)]&&hS[hQ(747)].runtime.id||""` (hQ(746)="NABBSnFnSnk=", hQ(747)="chrome", hQ(748)="runtime", hQ(749)="YjIXOCRfHQs=", hQ(386)="keys"). Captured payloads (sample/4, sample/5 decoded_payload_2.json): YjIXOCRfHQs= ["loadTimes","csi","app"], Q3M2OQUTNAM= "49e5084e", NABBSnFnSnk= "".

CreepJS

CreepJS, an open-source research demo rather than a production detector, counts a Blink runtime with no window.chrome as one of its "like headless" indicators.

src/headless/index.ts line 32, in the `likeHeadless` set: `noChrome: IS_BLINK && !('chrome' in window)`

Kasada

Probes for the window.chrome surface.

window_nav_info_no_chrome, iframe_nav_info_no_chrome

ips.js 427-probe teardown (emro.cat, Apr 2026)

DataDome

Ships window.chrome's own keys as a single field.

O1xeSh = ",loadTimes,csi,app"

glizzykingdreko/datadome-encryption — tests/original.json

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

Nearby checks in Automation surface

See all 27 checks in Automation surface
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 Automation surface 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 Automation surface — the family chrome-object belongs to.