Back to blog
·5 min read

What Is Browser Fingerprinting? A Developer's Guide

Browser fingerprinting is the process of collecting information about a browser's configuration and environment to create a unique identifier, a "fingerprint", that can distinguish one browser from another without cookies or login sessions.

If you build web scrapers, automated tests, or bot detection systems, understanding fingerprinting is essential. It's the core technique behind both detecting bots and evading detection.

How fingerprinting works

Browser fingerprinting was first studied in depth by the EFF's Panopticlick project (now Cover Your Tracks), which demonstrated that the combination of browser properties is almost always unique.

Every browser exposes hundreds of data points through standard Web APIs. Individually, these signals aren't unique. Combined, they form a fingerprint that's statistically unique across millions of browsers.

Here's what gets collected:

Navigator properties

The navigator object is the richest source of fingerprinting data:

navigator.userAgent       // "Mozilla/5.0 (Windows NT 10.0; Win64; x64)..."
navigator.platform        // "Win32"
navigator.language        // "en-US"
navigator.languages       // ["en-US", "en"]
navigator.hardwareConcurrency // 8
navigator.deviceMemory    // 8
navigator.maxTouchPoints  // 0 (desktop) or 5+ (mobile)
navigator.cookieEnabled   // true
navigator.pdfViewerEnabled // true

Screen and display

screen.width              // 1920
screen.height             // 1080
screen.colorDepth         // 24
window.devicePixelRatio   // 1 (standard) or 2 (HiDPI/Retina)
screen.availWidth         // 1920 (or less with vertical taskbar)
screen.availHeight        // 1040 (minus horizontal taskbar)

WebGL and GPU

WebGL reveals your graphics hardware:

const canvas = document.createElement('canvas')
const gl = canvas.getContext('webgl')
const ext = gl.getExtension('WEBGL_debug_renderer_info')
const vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL)   // "Google Inc. (Intel)"
const renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) // "ANGLE (Intel, Mesa Intel(R)...)"

GPU configurations vary widely and are hard to spoof consistently, making this one of the strongest fingerprinting signals.

Canvas fingerprinting

The same text rendered on different browser/OS/GPU combinations produces pixel-level differences due to different font rasterizers, anti-aliasing algorithms, and GPU drivers:

const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
ctx.font = '14px Arial'
ctx.fillText('fingerprint test', 2, 15)
const dataUrl = canvas.toDataURL() // Different data URL per browser/OS/GPU

The resulting data URL is typically hashed to create a compact fingerprint value.

Audio fingerprinting

The AudioContext API processes audio signals slightly differently depending on the platform's audio stack:

const ctx = new OfflineAudioContext(1, 44100, 44100)
const oscillator = ctx.createOscillator()
oscillator.type = 'triangle'
oscillator.frequency.setValueAtTime(10000, ctx.currentTime)
oscillator.connect(ctx.destination)
oscillator.start(0)
ctx.startRendering().then((buffer) => {
    // Hash the audio samples, varies by platform
    const samples = buffer.getChannelData(0)
})

Font detection

Available fonts vary by OS and installed software. Detection scripts test for font presence by rendering text with a candidate font and comparing the width against a generic fallback:

// If text rendered with "Segoe UI" has a different width
// than the same text with "monospace", the font is installed

Windows, macOS, and Linux each have distinct default font sets. Segoe UI is Windows-only, for example.

Timezone and locale

Intl.DateTimeFormat().resolvedOptions().timeZone // "America/New_York"
new Date().getTimezoneOffset()                    // 300 (EST is UTC-5)
Intl.NumberFormat().resolvedOptions().locale       // "en-US"

Note: getTimezoneOffset() returns a positive number when local time is behind UTC. For EST (UTC-5), the return value is 300 (not -300).

Why fingerprinting matters for bot detection

Automated browsers have fingerprints that look different from real users:

  1. Missing signals. Headless browsers may lack plugins, report a software GPU renderer, or have incomplete API implementations.
  2. Impossible combinations. A "Chrome on Windows" fingerprint with macOS-only fonts.
  3. Homogeneity. All instances in a headless browser farm may share identical fingerprints, unlike real users whose hardware and settings vary.
  4. Abnormal values. Zero plugins, SwiftShader as GPU renderer, or default viewport sizes like 800x600.

Detection systems combine these signals into a risk score. A few anomalies might be tolerated. A cluster of them triggers blocking.

Fingerprinting vs. cookies

Aspect Cookies Fingerprinting
Storage Client-side file Server-side computation
User control Can be deleted Cannot be "deleted"
Consent Required under GDPR Regulatory gray area
Uniqueness Explicit identifier Statistical identifier
Persistence Until expiry or deletion Until hardware/software changes
Evasion Clear cookies Change browser configuration

Fingerprinting is harder to evade because there's nothing to delete. The fingerprint is computed from your browser's inherent properties.

Fingerprint entropy

Not all signals contribute equally. Entropy measures how much each signal narrows down your identity. Higher entropy means more identifying power.

The EFF's 2010 Panopticlick study measured these approximate entropy values from a sample of ~470,000 browsers:

Signal Approximate entropy
Plugins ~15 bits
Fonts ~14 bits
User-Agent string ~10 bits
Screen resolution ~5 bits
Timezone ~3 bits

Canvas and audio fingerprinting were not measured in the original study but are widely used today.

You need roughly 33 bits of entropy to uniquely identify one person among 8 billion (since 2^33 ≈ 8.6 billion). Fingerprinting systems collect well over 33 bits, which is why they're effective.

Defensive fingerprinting

If you run automated browsers and want to avoid detection, the key principles are:

  1. Know your fingerprint. You can't fix what you can't see.
  2. Match a real profile. Your fingerprint should be consistent with a real browser on a real OS.
  3. Stay consistent. Every signal needs to agree with every other signal.
  4. Monitor for changes. Browser updates can alter your fingerprint.

Testing your fingerprint

StealthCheck analyzes your browser's fingerprint across 190+ checks in 9 scoring categories. It flags exactly which signals are anomalous and explains why.

Test your browser stealth for free

Run a free fingerprint test and see exactly what detection systems see.