What it measures
The signal reads three properties from globalThis.screen and globalThis.devicePixelRatio: width, height, and devicePixelRatio. These three values are joined and hashed. The colorDepth, availWidth, availHeight, and pixelDepth properties are also collected and stored in value.engine for diagnostics, but they are explicitly excluded from the hash.
Collection is synchronous and sub-millisecond. The signal uses the Firefox resistFingerprinting check to detect Firefox resistFingerprinting mode and downgrades confidence to degraded when it is active.
How it's collected
If globalThis.screen is undefined, the result is absent. Otherwise the collector reads screen.width, screen.height, and devicePixelRatio (defaulting to 1 if undefined), normalises the values, and hashes them with xxHash64. A separate Firefox-resistFingerprinting check fires on Firefox user agents whose reported screen dimensions match the bucketing pattern Firefox uses in that mode; the exact pattern is part of the internal detection recipe and not part of the public contract.
availWidth, availHeight, colorDepth, and pixelDepth are read into an auxiliary object and returned in value.engine for downstream diagnostics but never enter the hash concatenation.
Confidence rules
| Confidence | Trigger |
|---|---|
| normal | globalThis.screen is present and the Firefox resistFingerprinting check is false |
| degraded | the Firefox resistFingerprinting check returns true (Firefox resistFingerprinting bucketing detection) |
| absent | globalThis.screen is undefined, or an unhandled exception |
Why engine-bound
A 2026-05-20 cross-browser audit on an Apple M2 Pro Mac running Chrome, Safari, Firefox, and Brave revealed two independent reasons the signal cannot be treated as a cross-browser hardware signal. Safari reports colorDepth as 24 while Chromium and Firefox report 30 for the same display. Brave Shields Standard mode deterministically randomises width, height, and devicePixelRatio per eTLD+1, returning values like 1920x1080 at 1.79 or 1680x1050 at 2.0 on the same device, neither of which matches the actual display.
Removing colorDepth from the hash resolved the Safari divergence, but Brave farbling of the primary dimensions cannot be normalised away. The signal was reclassified as engine-bound to reflect that it provides per-browser-instance entropy rather than cross-browser device identity. It contributes to fingerprint but no longer to hardwareFingerprint.
Things worth knowing
- devicePixelRatio changes when the user zooms in or out (Ctrl+/Ctrl-). This causes hash instability across sessions if the zoom level changes between collections. The comparison layer accounts for this via a device-pixel-ratio zoom tolerance.
- screen.width and screen.height report the primary display dimensions. Secondary monitor configurations are not captured.
- Firefox resistFingerprinting bucketing detection downgrades the signal to degraded; the rounded values still carry some information, which is why the signal is degraded rather than absent.
- All property reads use null-safe access (?./) with defaults of 0 or 1 to avoid runtime errors in non-standard environments.
Last reviewed 2026-06-04

