the outer window fits within the screen
Check id window-bounds
What an ordinary browser yields
outerWidth and outerHeight are non-zero and fit within the reported full screen size, plus a 16px slack for the invisible resize borders Windows draws around maximized or snapped windows.
What a detector infers
The check asserts only the zoom-invariant bound: window.outerWidth/outerHeight must be non-zero and must fit within the screen. It deliberately does not assert inner ≤ outer, because zooming a page out legitimately grows innerWidth past outerWidth in an ordinary Chrome. The bound is calibrated for window-manager reality: Windows draws about 8px of invisible resize border at the left, right and bottom edges of a top-level window, so a maximized or snapped window legitimately reports outerWidth roughly equal to screen.width + 16 — and availWidth is smaller still once the taskbar is docked. The comparison therefore runs against the FULL screen size (not availWidth) with a 16px invisible-border plus 1px rounding slack; the earlier availWidth + 1px form false-positived on 9–27% of genuine desktop browsers with maximized or snapped windows. Two distinct signals remain. Zero outer dimensions mean no window is being presented — a visible window always reports real outer geometry. A window larger than the display even after the slack is the classic residue of a spoofed screen: the screen fields were shrunk to some persona's resolution while the actual window kept its real, larger size. A detector infers from either that the reported screen is not the surface the window lives on. Severity is warn.
How to resolve it
Size the window to fit the screen it claims. If a screen size is being set, pin the window to it at launch (an explicit --window-size within those bounds) so outerWidth/outerHeight, screenX/screenY and the screen fields all describe the same surface. Zero outer dimensions mean the browser has no visible window — give it a real or virtual display.
Read in the wild by
Kasada
Collects window.outerWidth/outerHeight and window.screenX/screenY, in both the main window and its injected iframe, in the same probe set as the screen fields (screen.width/height, availWidth/availHeight).
probes.txt: window_outer_width, window_outer_height, window_screen_x, window_screen_y, iframe_outer_width, iframe_outer_height — alongside window_screen_width, window_screen_height, window_screen_avail_width, window_screen_avail_height. blog.txt 427-probe slot map: "batch 4: fn_44072 -> 23 slots [... 199:window_outer_height(fn_46007) ...]", also 147:window_outer_width(fn_35510), 419:window_screen_x(fn_182073), 422:window_screen_y(fn_43907). Decompiled ips.js (2.txt) confirms these read window.screenX (not screen.x): func_008627 `r5 = a0["efg"]; return r5.screenX;`, func_00a274 `r4 = r4.efg["screenY"]`, func_012cf1 `r4.efg["outerWidth"]`, func_00ac52 `r4.efg["outerHeight"]` — where .efg = window_ref and .lbg = iframe_ref (func_004ce5 `r5.lbg.outerWidth`, func_016e02 `r5.lbg.outerHeight`).
PerimeterX / HUMAN
Computes and ships a dedicated boolean for whether the window's outer dimensions are zero — the field is sent true when outerWidth and outerHeight are not both 0 — alongside the raw, un-bucketed outerWidth/outerHeight and innerWidth/innerHeight plus screenX/screenY, all read from window.
Deployed PX collector main.min.js (captured from ifood; /root/re/PerimeterX_RE/stample/ifood/source/main.min.js), where hS=window. Function Cm(t): `t[hQ(794)]=!(0===hS.outerWidth&&0===hS[hQ(795)])` with hQ_map 794="PSkIY3tJCVI=", 795='outerHeight' — note the leading `!`, so the field is true when the window is NOT zero-sized. The same Cm also collects `t["NABBSnFjS34="]=hS.screenX`, `t["R3cyPQIUOAg="]=hS[hQ(786)]` (786='screenY'), `t[hQ(787)]=hS[hQ(788)]||-1` (787="Dz96dUlecUM=", 788='innerWidth') and `t[hQ(789)]=hS[hQ(790)]||-1` (789="HUloQ1goa3A=", 790='innerHeight'). The raw outer dimensions are in the adjacent function Co(t): `t[hQ(809)]=Cz(hS[hQ(810)])` (809="KnpfcG8eWEI=", 810='outerWidth') and `t["Hm4rZFgNLFc="]=Cz(hS.outerHeight)`, where `function Cz(t){var n=parseFloat(t);if(!isNaN(n))return n}` — a bare parseFloat, no bucketing. All six keys appear in a captured decoded EV2 payload (stample/ifood/sample/1/decoded_payload_2.json: PSkIY3tJCVI==true, KnpfcG8eWEI==1050, Hm4rZFgNLFc==832, Dz96dUlecUM==1037, HUloQ1goa3A==683, NABBSnFjS34==10); the field map for the same case (bug_report/sdk_drift_cases/2026-05-19_ifood/all_fields_map.json) records true/1440/852/515/731/0. Base64 keys are rotated per bundle, so these names are specific to this capture — the same `!(0===outerWidth&&0===outerHeight)` construct appears in two other independently-obfuscated deployed bundles: walmart `e["GmEhYFwKLlE="]=!(0===eM.outerWidth&&0===eM.outerHeight)` and totalwine `i[im(792)]=!(0===ip.outerWidth&&0===ip[im(793)])`.
CreepJS
CreepJS, a research demo rather than a production detector, compares window geometry against the reported screen — innerWidth/outerHeight, and visualViewport's dimensions — and its `hasVvpScreenRes` flag counts an exact match toward the "like headless" rating.
src/headless/index.ts, `likeHeadless` object, flag `hasVvpScreenRes`: `hasVvpScreenRes: ((innerWidth === screen.width && outerHeight === screen.height) || ('visualViewport' in window && (visualViewport.width === screen.width && visualViewport.height === screen.height)))` — rendered as `${likeHeadlessRating}% like headless:`
Every attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Screen & display
- screen dimensions are a plausible physical size
screen-plausibleA pure sanity range on screen.width and screen.height: both must be at least 200px and no more than 16384px. - the available screen area fits inside the screen
screen-avail-within-boundsThe available screen area is a subset of the screen by definition: availWidth and availHeight describe what is left of width and height… - screen.colorDepth decomposes into the CSS color media feature
color-depth-vs-media-colorscreen.colorDepth and the CSS color media feature describe one display in two different units: total bits per pixel, and bits per colour… - screen has an OS chrome inset (avail < screen on either axis)
taskbar-presentscreen.availWidth/availHeight describe the area left over after the OS reserves space for its own chrome — a Windows taskbar, a macOS dock… - a non-touch desktop has a fine pointer + hover
pointer-hover-desktopThis check applies only when the UA identifies a desktop platform (Windows, Macintosh, Mac OS X, X11, Linux, CrOS, and not Android/Mobile)… - maxTouchPoints coheres with pointer media
touch-pointer-coherenceA one-directional coherence test: if navigator.maxTouchPoints is greater than zero, matchMedia("(any-pointer: coarse)") is expected to… - screen dimensions resolve via native prototype getters
screen-descriptorsFor width, height, availWidth, availHeight, colorDepth and pixelDepth this asks two questions: does the screen instance carry an own… - screen.orientation agrees with the screen's own dimensions
orientation-vs-screen-dimsscreen.orientation.type and screen.width/height are both device-space values sourced from the same display metrics, so they must agree: a…
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 Screen & display 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 Screen & display — the family window-bounds belongs to.