Signal

Screen frame

Captures the four offsets between the physical screen and the area available to web content (menu bar, taskbar, Dock), exposing OS chrome state independent of the screen signal.

Reviewed

Tier 1 engine

What it measures

Four pixel offsets, each rounded to a small fixed bucket: top = screen.availTop (OS menu bar or top-taskbar), left = screen.availLeft (sidebar dock or left-taskbar), right = screen.width − screen.availWidth − screen.availLeft (sidebar dock on the opposite edge), bottom = screen.height − screen.availHeight − screen.availTop (bottom dock or bottom-taskbar). The exact rounding granularity is part of the internal recipe and not part of the public contract.

Distinct from the screen signal. screen captures width / height / devicePixelRatio; screen_frame captures the chrome around them. Two devices with identical resolutions still produce different screen_frame hashes if one has the Dock on the bottom and the other on the left.

Why round

OS-chrome auto-hide behaviours move the underlying offsets across a small range as the user hovers or animates the dock or taskbar. The rounding step is sized so that the hash stays stable across hover state and minor browser-chrome variance between fullscreen and split-view modes, capturing 'dock is on this edge' rather than the millisecond-by-millisecond geometry.

Negative offsets (which can occur when a browser window straddles monitor boundaries) are clamped to zero before bucketing. This protects the hash from garbage in multi-monitor edge cases.

Confidence rules

ConfidenceTrigger
normalAll six screen fields readable as numbers; the Firefox resistFingerprinting check is false
degradedAll fields readable but the Firefox resistFingerprinting check is true, so every offset collapses to 0 by Firefox's design
absentglobalThis.screen is undefined or required fields are non-numeric

Things worth knowing

  • On mobile (iOS Safari, Android Chrome), all four offsets are typically 0 because the web view fills the screen. Hash is the all-zero bucket; near-zero entropy on phones but a useful tablet-vs-phone discriminator (iPad in split-view mode reports non-zero offsets).
  • OS-level 'Always show menu bar' toggles change the top offset, so the hash changes when the user toggles the setting. This is real user-preference entropy.
  • DPI scaling does not affect the values, because offsets are reported in CSS pixels independent of devicePixelRatio. A 2× retina display reports the same offsets as a non-retina display at the same logical size.
  • Dev-tools docked to the page does NOT affect screen.*; it modifies window.innerWidth only. Hash stays stable across opening / closing dev tools.
  • FingerprintJS collects screen_frame (their sources/screen_frame.ts uses replaceNaN rounding); Thumbmark does not. Adopting it brings us to FingerprintJS parity and net-positive vs Thumbmark.

Last reviewed 2026-06-04