Browser Fingerprinting Explained: How Websites Identify You Without Cookies

Canvas, WebGL, AudioContext, fonts, screen resolution -- how dozens of signals combine into a unique fingerprint. What detection systems look for, and why most "privacy" tools fail to address it.

In this article
  1. What Is Browser Fingerprinting?
  2. The Fingerprint Signals
  3. How Fingerprints Are Calculated
  4. Entropy: Why Some Signals Matter More Than Others
  5. Active vs. Passive Fingerprinting
  6. How Detection Systems Use Fingerprints
  7. Why Standard Privacy Tools Don't Work
  8. How Anti-Detect Browsers Handle Fingerprinting
  9. The Arms Race

What Is Browser Fingerprinting?

Browser fingerprinting is a tracking technique that identifies users by collecting information about their browser and device configuration. Unlike cookies, which are stored on your device and can be deleted, a fingerprint is computed from data your browser exposes by default -- information that exists because websites need it to function correctly.

Your browser reveals your operating system, screen resolution, timezone, language, installed fonts, GPU model, audio processing characteristics, and much more. Individually, none of these data points identify you. Combined, they create a signature that is unique to your specific browser on your specific device with overwhelming probability.

A 2020 study by researchers at INRIA found that over 94% of browsers with JavaScript enabled had unique fingerprints. The situation has only gotten more precise since then, as detection companies have added new signals and improved their hashing algorithms.

The Fingerprint Signals

There are over 50 individual signals that contribute to a browser fingerprint. Here are the most important ones:

High Entropy
Canvas Fingerprint

The browser draws invisible text and shapes on an HTML5 canvas element, then reads back the pixel data. Different GPUs, drivers, font renderers, and OS-level anti-aliasing settings produce subtly different output -- enough to generate a nearly unique hash.

High Entropy
WebGL Fingerprint

Similar to canvas but uses 3D rendering. The browser renders a 3D scene, and the output varies based on GPU hardware, driver version, and OpenGL implementation. Also exposes the GPU vendor and renderer strings (e.g., "ANGLE (NVIDIA GeForce RTX 3080)").

High Entropy
AudioContext Fingerprint

The browser generates an audio signal using the Web Audio API and measures how it's processed. Different audio hardware and drivers produce different floating-point output, creating a unique audio hash without ever playing sound.

High Entropy
Font Enumeration

The browser measures the rendered width and height of text in various fonts. By checking which fonts are installed (and how they render), a fingerprinting script can identify your specific set of installed fonts -- which varies significantly between machines.

Medium Entropy
Screen & Window Metrics

Screen resolution, available screen size (minus taskbar), color depth, device pixel ratio, window inner dimensions, and whether the window is maximized. The combination of these values narrows identification significantly.

Medium Entropy
Navigator Properties

User agent string, platform, language(s), number of CPU cores (hardwareConcurrency), device memory, maximum touch points, connection type, and whether "Do Not Track" is enabled. Each adds a few bits of entropy.

Beyond these primary signals, fingerprinting scripts also collect:

How Fingerprints Are Calculated

A fingerprinting script collects all of these values, serializes them into a string or structured object, and runs them through a hash function (typically MurmurHash3 or SHA-256) to produce a compact identifier. Here's a simplified example:

const signals = {
  canvas: getCanvasHash(),
  webgl: getWebGLHash(),
  audio: getAudioHash(),
  fonts: getInstalledFonts(),
  screen: `${screen.width}x${screen.height}x${screen.colorDepth}`,
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
  language: navigator.language,
  cores: navigator.hardwareConcurrency,
  memory: navigator.deviceMemory,
  platform: navigator.platform,
  userAgent: navigator.userAgent,
  touchPoints: navigator.maxTouchPoints,
  // ... 30+ more signals
};

const fingerprint = murmurhash3(JSON.stringify(signals));

The resulting hash is a short string -- something like a3f8c91b -- that serves as your browser's unique ID. This hash is stored server-side and compared against future visits.

Entropy: Why Some Signals Matter More Than Others

Not all signals contribute equally to uniqueness. The concept of entropy measures how much identifying information a signal carries. Higher entropy means more bits of information, which means the signal does more to narrow down your identity.

SignalApproximate EntropyUniqueness Impact
Canvas hash~14 bitsVery high -- GPU and rendering differences
WebGL renderer + hash~12 bitsVery high -- identifies GPU model
Installed fonts~11 bitsVery high -- varies per machine
AudioContext hash~10 bitsHigh -- hardware-dependent
Screen resolution~5 bitsMedium -- many share common resolutions
Timezone~4 bitsMedium -- ~24 major timezone groups
User agent~6 bitsMedium -- browser version adds specificity
Language~3 bitsLow -- limited set of common languages
Platform~2 bitsLow -- Win/Mac/Linux/Mobile
Color depth~1 bitVery low -- almost everyone is 24-bit

The total entropy across all signals in a modern fingerprinting script typically exceeds 40 bits. With 40 bits of entropy, there are over 1 trillion possible combinations -- more than enough to uniquely identify every browser on Earth.

Active vs. Passive Fingerprinting

Fingerprinting techniques fall into two categories:

Passive fingerprinting uses data the browser sends automatically with every HTTP request: the user agent header, accepted languages, accepted encodings, and connection characteristics. The server doesn't need to run any JavaScript. This is stealthier but provides fewer signals.

Active fingerprinting runs JavaScript on the page to probe the browser: rendering canvas images, querying WebGL, measuring audio output, enumerating fonts, and checking for specific API behaviors. This is far more powerful and is what most detection systems rely on.

In practice, detection systems use both. The passive fingerprint from HTTP headers is computed on the server side, while the active fingerprint is computed client-side via JavaScript and sent back as a signal. The two are combined and cross-checked for consistency.

How Detection Systems Use Fingerprints

Browser fingerprints aren't used in isolation. Modern detection platforms combine them with other signals to build a risk score:

The fingerprint itself is just one input. What really matters is the consistency and plausibility of the entire signal package. A perfect fingerprint with a datacenter IP and robotic mouse movements will still get flagged.

Why Standard Privacy Tools Don't Work

Users often turn to privacy tools that are ineffective against fingerprinting:

Incognito / Private Browsing

Incognito mode clears cookies and history when the window closes. It does nothing to the fingerprint. Your canvas hash, WebGL output, fonts, screen resolution, and every other signal remains identical to your normal browsing session. The same fingerprint, just without cookies.

VPN / Tor

VPNs change your IP address. Tor also standardizes some browser properties through the Tor Browser. However, regular VPNs don't modify the browser fingerprint at all -- your canvas hash and WebGL renderer stay the same. And Tor Browser, while it does resist fingerprinting, is recognizable as Tor Browser itself, which many platforms block outright.

Browser Extensions

Extensions like Canvas Blocker or Fingerprint Spoofing add-ons try to intercept fingerprinting APIs. The problem is threefold: (1) extensions can be detected via their side effects on the DOM and API behavior, (2) they can't consistently spoof signals that originate below the JavaScript layer, and (3) the presence of specific privacy extensions is itself a fingerprint signal -- very few real users have them installed.

Multiple Browser Profiles (Chrome/Firefox)

Chrome and Firefox support multiple user profiles, and each has separate cookies and history. But they all share the same fingerprint because they're the same browser on the same hardware. Different profiles, same canvas hash, same WebGL, same fonts. Detection systems link them immediately.

How Anti-Detect Browsers Handle Fingerprinting

Anti-detect browsers are specifically designed to address fingerprinting at its source. Here's what a well-built one does differently:

Per-profile fingerprint configuration. Each browser profile gets its own complete fingerprint configuration: a specific canvas noise seed, a spoofed WebGL renderer matching a real GPU, a set of fonts consistent with the chosen OS, screen metrics that match a real device, and so on. The key is that all these values are consistent with each other.

Engine-level modification. In a properly built anti-detect browser, the fingerprint modifications happen inside the browser engine -- at the C++ level in Chromium. When a website calls canvas.toDataURL(), the engine itself returns modified pixel data. There's no JavaScript override to detect because the modification happens before the data reaches the JavaScript layer.

Noise injection with stable seeds. Rather than returning random values (which would change on every page load and get flagged), good anti-detect browsers use deterministic noise based on a per-profile seed. The same canvas test always produces the same hash within a profile, but different profiles produce different hashes. This mimics how real browsers behave -- your fingerprint is stable across sessions.

Hardware plausibility validation. Before generating a profile, the system validates that the combination of signals is plausible. A profile claiming to be Windows 10 with an Apple M2 GPU would be immediately suspicious. The fingerprint generator ensures that OS, GPU, fonts, user agent, and other signals form a coherent identity.

The goal isn't to make a browser that looks "anonymous." It's to make a browser that looks like an ordinary person using an ordinary computer -- just a different ordinary person for each profile.

The Arms Race

Browser fingerprinting is an arms race between detection companies and anti-detect tools, and it's accelerating.

Detection systems are getting more sophisticated. They're adding new signals (like getClientRects() measurements and WebCodecs API behavior), cross-referencing behavioral biometrics with fingerprint data, and using machine learning to identify "impossible" or "improbable" fingerprint configurations that no real browser would produce.

At the same time, anti-detect browsers are responding by modifying deeper layers of the browser engine, improving fingerprint consistency checks, and building more comprehensive databases of real-world device configurations to use as templates.

Two things are clear: fingerprinting isn't going away (it's too valuable for fraud prevention and ad targeting), and passive tools like VPNs and extensions aren't enough to address it. If fingerprint-level isolation matters to your workflow, you need a tool that was built specifically for the job.

Built at the engine level

P8's custom Chromium engine handles fingerprint generation at the source code level -- not through JS patches. Each profile produces a consistent, plausible fingerprint.

Start for Free
All articles Prev: What Is an Anti-Detect Browser?