Skip to content

Timing Fingerprinting

Timing fingerprinting measures performance.now() precision and timezone information. Timer resolution reveals the browser's privacy settings and environment type.

Collected signals

SignalWhat it measures
timerResolutionSmallest non-zero diff between performance.now() calls (20 samples)
timezoneOffsetnew Date().getTimezoneOffset() in minutes
timezoneIntl.DateTimeFormat().resolvedOptions().timeZone (e.g. Europe/Warsaw)
dateResolutionDiff between two Date.now() calls
performanceTimelineWhether performance.getEntries() is available

Why timer resolution matters

  • Normal Chrome/Safari: ~0.005ms (high precision)
  • Firefox resistFingerprinting: rounded to 100ms
  • VM/emulated environments: abnormally consistent or zero

Entropy and stability

PropertyValue
Entropy~5 bits
Stability0.60
Typical duration<1ms

Web Worker offloading

Timing runs in a Web Worker by default. performance.now() is available in Worker contexts.

Usage

ts
const fp = await neoprint.get({ collectors: ['timing'] })
const t = fp.components.timing.value

console.log(t.timezone)         // "Europe/Warsaw"
console.log(t.timerResolution)  // 0.005 (normal) or 100 (resistFingerprinting)

Released under the MIT License.