pageXOffset/pageYOffset match their scrollX/scrollY aliases
Check id scroll-alias-coherence
What an ordinary browser yields
pageXOffset equals scrollX and pageYOffset equals scrollY, exactly, because each pair is one value with two names.
What a detector infers
window.pageXOffset is not a second scroll position, it is a legacy alias of window.scrollX — the specification defines them as the same value and Blink backs both names with one getter. The same holds for pageYOffset and scrollY. Two names, one number, so they are incapable of disagreeing in a real browser. That makes this a complete test of whether both names still reach the same place, and it costs two property reads. The shape it catches is a familiar one: a value rewritten through the name a script is expected to read, while the alias nobody remembered keeps reporting the truth. It is the same class of mistake as patching navigator.language and forgetting navigator.languages[0]. Worth noting that Kasada reads pageXOffset and pageYOffset and never scrollX or scrollY — reading only one name of an aliased pair is what makes the pair assertable by someone who reads both.
How to resolve it
Do not patch one name of an aliased pair. If a scroll position must differ, scroll the document — the alias is not a second source that can be updated to match, it is the same source, and the disagreement itself is the tell.
Read in the wild by
Kasada
Reads pageXOffset/pageYOffset and never scrollX/scrollY — reading only one name of an aliased pair is what leaves the pair assertable by someone who reads both.
window_page_x_offset, window_page_y_offset
Kasada ips.js teardown — the full 427-probe listEvery attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Automation surface
- user activation only ever appeared after a real input event
activation-without-inputThe row above this one reads navigator.userActivation once and expects it to be true, because the audit is reached by pressing a button. - the clicks this page received were real clicks
interaction-click-trustEvent.isTrusted is set by the engine when it dispatches an event it generated itself, and it cannot be set from script - a constructed… - every keypress had a keydown behind it
interaction-keypress-without-keydownThe UI Events spec generates keypress as the DEFAULT ACTION of a keydown - it is not an independent event, it is what a keydown does when it… - key events named the key they carried
interaction-key-identity-populatedA keypress the engine generates names the character it is delivering in .key. - the dropdown change came from the browser, not from a script
interaction-select-change-trustThe same isTrusted argument as the click row, on the surface where the shortcut is most common. - the dropdown fired input before change
interaction-select-input-precedes-changeHTML's "send select update notifications" steps fire input and THEN change when a selection is committed, so the pair is what the algorithm… - no automation pointer-flash artifact is present
pointer-flash-keyframe-artifactThe only row on this page that works by recognising a specific string, which needs justifying because a name table is exactly what this… - a focused child frame implies its parent document is focused
document-focus-vs-realmdocument.hasFocus() is true when the document OR any of its descendants holds focus, which makes it hierarchical rather than local: 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 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 scroll-alias-coherence belongs to.