IANA zone offset matches the JS clock offset (incl. across DST)
Check id timezone-offset-coherence
What an ordinary browser yields
Both paths report the same minute offset for the resolved zone, e.g. 'IANA Europe/Amsterdam and Date both = 120min'.
What a detector infers
This is a two-source cross-check on the same fact. It takes the resolved IANA zone, formats the current instant through `Intl.DateTimeFormat` with that timeZone, reconstructs the wall-clock time as a UTC timestamp, and derives the implied offset in minutes. It then compares that against `-new Date().getTimezoneOffset()`, allowing 1 minute of slack for the second boundary. Intl and Date read the timezone through different internal paths, so a spoof applied to only one of them produces two numbers that disagree — a layered lie. A detector does not need to know your real zone to score this: the contradiction is self-contained and provable from inside the page. N/A when no zone resolves.
How to resolve it
Spoof the timezone at the engine level so Intl and Date derive from one source (geoip/timezone in clearcote). Do not patch `Date.prototype.getTimezoneOffset` or `Intl` in userland JS — patching one leaves the other reporting the host's real offset.
Read in the wild by
PerimeterX / HUMAN
Its main.min.js collector reads the offset via a wrapper that returns the sentinel 9999 if the read throws, and ships that number in the same payload object as the Intl-resolved IANA zone and the rendered Date() string.
main.min.js `CD(){try{return(new Date).getTimezoneOffset()}catch(t){return 9999}}`, assigned at L8037 by `t[0]["OARNTn5iRnw="]=CD()`; same file sets the Intl zone at L5217 (`t[hQ(359)]=n.resolvedOptions()[hQ(360)]`, catch-fallback `t["UT0kdxRdI0Y="]="undef"`) and the Date string at L7898 (`t["Czt+cU1WeEM="]=hS[hQ(802)]()`). All three keys travel in one EV2 object: "OARNTn5iRnw=" = -480, "UT0kdxRdI0Y=" = "Asia/Shanghai", "Czt+cU1WeEM=" = "Tue May 19 2026 03:15:54 GMT+0800 (中国标准时间)"
CreepJS
CreepJS, an open-source research and education demo rather than a production detector, cross-checks the offset the host derives through Date against the offset implied by its Intl-resolved zone for the same instant (evaluated at a historical year, 1113), and when the two disagree it stops trusting the reported zone and re-derives a candidate city set from the Date offset instead — what it calls the zone failing to decrypt to itself.
src/timezone/index.ts L518-530: `const system = getTimezoneOffsetHistory({ year })` and `const resolvedOptions = getTimezoneOffsetHistory({ year, city: timeZone })`, compared at L525 `system == resolvedOptions ? [timeZone] : binarySearch(cities, filter)`, resolved at L530 `decryption.length == 1 && decryption[0] == timeZone ? timeZone : hashMini(decryption)`; year fixed at 1113 (L552); the no-city branch derives the host offset from Date alone (L500-505, `+new Date('7/1/1113')` vs `+new Date('1113-07-01')`), the city branch via `new Intl.DateTimeFormat('en', {timeZone: city})` (L499). Secondary (a Date-vs-Date cross-check, not Date-vs-Intl): `offset: new Date().getTimezoneOffset()` and `offsetComputed: getTimezoneOffset()` (L563-564), surfaced side by side at L604. Lie gate L546-550: `lieProps['Date.getTimezoneOffset'] || lieProps['Intl.DateTimeFormat.resolvedOptions']`, which marks the panel `rejected` at L597.
Kasada
Reads the zone as a string and the offset as a number, in both realms.
window_timezone_offset / iframe_timezone_offset, window_timezone_string / iframe_timezone_string
ips.js 427-probe teardown (emro.cat, Apr 2026)
Akamai
Lists Date.getTimezoneOffset() under browser-fingerprint signals.
signal_categories.md - 1. Browser Fingerprint - Timezone offset
Edioff/akamai-analysis — signal_categories.mdEvery attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Environment & locale
- Intl timezone resolves
timezone-presentThis check reads Intl.DateTimeFormat().resolvedOptions().timeZone and records it alongside -new Date().getTimezoneOffset() and… - timezone is not UTC
timezone-not-utcThe check resolves the Intl zone and fails only when it is exactly 'UTC' or 'Etc/UTC'. - navigator.plugins is consistent with the PDF viewer
has-pluginsAn empty navigator.plugins is only meaningful when it contradicts something else, and this check is written to respect that. - navigator.pdfViewerEnabled is true
pdf-viewerA direct read of navigator.pdfViewerEnabled. It is N/A when the property is not exposed at all, passes when true, and is marked false… - mimeTypes are consistent with navigator.plugins
plugins-mimetypesThis walks navigator.mimeTypes, and for each entry reads .enabledPlugin and checks that the exact object is present in a Set built from… - proprietary codecs (H.264 / AAC) present for a Chrome UA
codec-supportThe check calls canPlayType on a video and audio element for H.264 ('avc1.42E01E') and AAC ('mp4a.40.2'), plus MP4/WebM/Ogg for context, and… - Blink-only Web APIs present for a Chrome UA
blink-web-apisWhen the UA matches Chrome/\d+ and the page is a secure context, this probes four Blink-only surfaces: navigator.connection… - CSS feature support matches the engine (Blink for a Chrome UA)
css-engine-surfaceFor any UA containing 'Chrome/', this requires CSS.supports('-webkit-app-region', 'drag') to be true and the Gecko markers — MozAppearance…
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 Environment & locale 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 Environment & locale — the family timezone-offset-coherence belongs to.