What Is Window Property Fingerprinting? β Definition and How It Works
Learn how the window object's property inventory identifies browsers, automation tools, and injected scripts.
Window property fingerprinting enumerates the global object's properties and uses what is present, absent, or unexpected as an identifying signal.
1. The Global Object Is an Inventory
window holds every global API the browser exposes, plus anything scripts on the page have added. Enumerating it produces a list that varies by browser, version, platform, and β critically β by what automation or extensions have injected.
Object.getOwnPropertyNames(window).length // varies by browser and build
The count alone is weakly identifying. The specific set is much stronger, because API availability differs precisely between browser versions.
2. Automation Artefacts Live Here
Historically, automation tools left recognisable globals. The pattern that detection relies on:
| Property shape | Suggests |
|---|---|
cdc_-prefixed properties |
ChromeDriver artefacts |
_selenium, callSelenium |
Selenium injection |
__webdriver_*, __driver_* |
WebDriver variants |
__playwright*, __puppeteer* |
Framework injection |
__nightmare |
Older automation tooling |
Unexpected domAutomation* |
Automation harness |
A single unexpected global of this shape is close to conclusive, which is why removing them is the first thing stealth configurations attempt β and why a scan for unknown globals is a cheap, high-yield check for defenders.
3. Anti-Bot Scripts Are Detectable the Same Way
The technique cuts both directions. Anti-bot and fraud vendors also define globals, which is how you identify them:
['BNQL', 'ArkoseEnforcement', 'hcaptcha', 'grecaptcha', 'initGeetest',
'kpsdk', '_pxAppId', '__CF$cv$params']
.filter(p => p.split('.').reduce((o, k) => o && o[k], window) !== undefined)
That is exactly the window signal class an anti-bot detector uses, and it only works after JavaScript has executed β a plain HTTP fetch sees none of it.
4. Absence Is a Signal Too
Missing APIs matter as much as extra ones:
- A current Chrome build without
RTCPeerConnectionβ WebRTC disabled, unusual. - No
chromeobject on a browser claiming to be Chrome. - Missing
navigator.userAgentDataon a Chromium version that should have it. - No
NotificationorPushManagerwhere the claimed browser provides them.
Each absence usually means a deliberate override, which is the thing detection is looking for.
5. Version Consistency
API availability tracks browser version closely. A user agent claiming a recent version must expose that version's APIs:
// A UA claiming a recent Chromium, with an API that version should have
'userAgentData' in navigator
'showOpenFilePicker' in window
CSS.registerProperty !== undefined
Spoofing the user agent to a newer version than the actual binary creates a mismatch β the claim says one thing, the API surface says another. Spoofing to an older version has the same problem in reverse: APIs present that the claimed version never shipped.
6. Iframe Comparison
A subtle technique: create a clean iframe and compare its window against the page's.
const f = document.createElement('iframe');
document.body.appendChild(f);
const clean = Object.getOwnPropertyNames(f.contentWindow);
const here = Object.getOwnPropertyNames(window);
const extra = here.filter(p => !clean.includes(p));
Properties present in the page but not in a fresh iframe were added by something. Stealth patches applied only to the main frame β a common shortcut β are exposed immediately by this comparison.
7. Practical Implications
For collection: minimise what you inject. Every added global is a signal. Prefer a browser that needs no injection, and if you must patch, apply changes consistently to every frame, not just the top one.
For identification: window enumeration is the most reliable way to name the anti-bot or CAPTCHA vendor on a page, but it requires script execution β so it belongs in a browser-based probe, not an HTTP one.
8. Summary
Window property fingerprinting enumerates the global object and reads both additions and absences: automation artefacts like cdc_ and __playwright*, vendor globals that identify anti-bot products, and missing APIs that reveal overrides or a spoofed version.
The iframe comparison is the technique to know β properties present in the page but absent from a fresh iframe were injected β and it defeats stealth patches applied only to the main frame.