fingerprintby Scraping Central
Menu

Timezone & locale

Your Time and Language Fingerprint

IANA timezone, UTC offset, navigator.languages order, calendar system, numbering system, and week-start day.

Timezone & locale

Reading signal in your browser...

Cross-checks anti-bot systems run

  • IANA timezone vs geo-IP. Delta > a few hours = flag.
  • navigator.languages[0] vs Accept-Language. They should share a prefix.
  • Calendar / numbering system vs locale. Non-gregorian calendars on a US locale are suspicious.
  • Empty navigator.languages. Real browsers always send at least one entry.

Consistent locale setups

Match all four: timezone (TZ env var or emulateTimezone), navigator.languages (set via CDP), Accept-Language header (extraHTTPHeaders), and Intl.NumberFormat / Intl.DateTimeFormat defaults (fall out of the OS locale, typically). If you skip any one, you leak.

Frequently asked questions

How does a website read my timezone?

Intl.DateTimeFormat().resolvedOptions().timeZone returns your IANA zone (like 'Europe/Warsaw' or 'America/New_York'). It comes from your OS setting, or from Chromium's TZ environment variable in Node/CDP contexts. new Date().getTimezoneOffset() gives the numerical offset.

Why is timezone the classic mismatch signal?

Because it's the easiest cross-check against your IP. If your proxy exits in Berlin (Europe/Berlin) but your browser reports Asia/Kolkata, you're a scraper who forgot to set TZ. Bot detectors compute the mismatch delta and use it as a strong flag.

What is navigator.languages and why does its order matter?

An ordered list of language tags (e.g. ['en-US', 'en', 'es']). The order reflects the user's preference. Real browsers get it from the OS. Headless Chrome without configuration often reports ['en-US', 'en'] regardless of locale, which is an easy tell if your UA claims a French Chrome.

What's a locale beyond just the language?

A locale bundles language, region, calendar system, numbering system, first day of the week, and formatting conventions (dates, currency, decimal separator). Intl.Locale exposes them programmatically. Tampering with one but not the others creates internal inconsistency.

How do I set timezone and locale in Playwright / Puppeteer?

Playwright: newContext({ timezoneId: 'Europe/Warsaw', locale: 'pl-PL' }). Puppeteer: page.emulateTimezone() and either the --lang flag or CDP's Emulation.setLocaleOverride. Always pair with matching Accept-Language via extraHTTPHeaders.

← Run the full fingerprint report

AI Summary

Summarize this page in your favorite LLM