You can block cookies. You can use incognito mode. You can install every privacy extension in the Chrome Web Store. And websites can still identify you with over 99% accuracy, without storing a single byte of data on your machine.
This is browser fingerprinting. It works because the combination of attributes your browser exposes -- screen resolution, installed fonts, GPU renderer, timezone, language, and dozens of other signals -- is almost always unique. Not probably unique. Practically unique among millions of browsers.
I started taking this seriously when I read a 2016 study from Lehigh University that found 99.24% of browsers had a unique fingerprint out of a sample of 118,934. A follow-up study in 2020 by researchers at KU Leuven found similar results with modern anti-tracking measures in place. The fingerprint adapts. It doesn't go away.
What your browser tells every website you visit
Open your browser's developer console and type navigator.userAgent. You'll get a string that includes your browser name, version, operating system, and sometimes your device type. That alone isn't very identifying. But it's one signal in a much larger set.
Here's a partial list of what JavaScript can access without any permissions:
-
Screen resolution and color depth:
screen.width,screen.height,screen.colorDepth. Your exact display configuration. -
Timezone:
Intl.DateTimeFormat().resolvedOptions().timeZone. Narrows you to a geographic region. -
Language and locale:
navigator.languages. The ordered list of preferred languages. -
Platform:
navigator.platform. The operating system. -
Hardware concurrency:
navigator.hardwareConcurrency. The number of logical CPU cores. -
Device memory:
navigator.deviceMemory. Approximate RAM in gigabytes. -
Touch support:
navigator.maxTouchPoints. Whether you have a touchscreen and how many simultaneous touch points it supports.
None of these require permission prompts. They're considered part of the "standard" browser API. Individually, each has low entropy -- millions of people have 1920x1080 screens. But combined, the entropy adds up fast.
Canvas fingerprinting
This is the technique that made browser fingerprinting mainstream. The browser's Canvas API lets JavaScript draw graphics and read back the pixel data. The way your system renders text and shapes depends on your GPU, graphics driver, operating system, installed fonts, and anti-aliasing settings. These tiny rendering differences produce measurably different pixel values across machines.
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillStyle = '#f60';
ctx.fillRect(125, 1, 62, 20);
ctx.fillStyle = '#069';
ctx.fillText('fingerprint', 2, 15);
const dataURL = canvas.toDataURL();
// dataURL is now a unique-ish string based on how YOUR system rendered this
The resulting data URL is hashed and becomes part of your fingerprint. Two machines with different GPUs will produce different hashes even if everything else is identical. The EFF's Panopticlick project found canvas fingerprinting adds roughly 10 bits of entropy to a fingerprint.
WebGL fingerprinting
Similar concept, deeper signal. WebGL exposes your GPU renderer string, vendor, supported extensions, shader precision format, and maximum texture sizes. The WEBGL_debug_renderer_info extension literally returns your graphics card model.
const gl = canvas.getContext('webgl');
const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
// Returns something like "ANGLE (NVIDIA GeForce RTX 3080, D3D11)"
Combined with the rendering behavior of specific WebGL operations, this creates a hardware-level fingerprint that's extremely difficult to spoof.
AudioContext fingerprinting
Your browser's AudioContext API processes sound signals in a way that varies based on the audio stack -- hardware, drivers, and software processing. By creating an oscillator, running it through a compressor, and reading the output values, a script can generate a fingerprint from tiny floating-point differences in audio processing.
No sound is actually played. The processing happens silently. The user has no idea.
Font enumeration
Browsers don't provide a direct API to list installed fonts. So fingerprinting scripts use a side-channel: they render text in a known default font, measure the width and height, then try the same text in a list of hundreds of target fonts. If the dimensions change, the font is installed. The set of installed fonts is surprisingly unique because it reflects your operating system, language packs, and any applications you've installed that bundle fonts (Adobe products, Microsoft Office, etc.).
What doesn't work to prevent fingerprinting
Incognito mode does nothing. It prevents cookie storage and local history. It doesn't change your fingerprint. Your screen, GPU, fonts, and hardware are the same.
VPNs hide your IP address. They don't touch any of the JavaScript-accessible attributes. IP is actually one of the weaker fingerprinting signals because it changes when you move networks.
Cookie blockers prevent server-side tracking via cookies. Fingerprinting is entirely client-side computation that requires no storage.
User-agent spoofing changes one signal. If the rest of your fingerprint stays the same, the mismatched user-agent actually makes you more unique, not less.
What does work
The Tor Browser is the gold standard. It normalizes screen size, blocks canvas and WebGL readback, standardizes fonts, and reports a generic user-agent. The goal is to make every Tor user look identical, which means your individual entropy drops to near zero. The trade-off is significant usability cost.
Firefox's Enhanced Tracking Protection includes some fingerprinting resistance, and the privacy.resistFingerprinting flag in about:config goes further by reporting a standard screen size, timezone, and locale. Brave browser blocks known fingerprinting scripts and randomizes canvas output so it changes every session while still rendering correctly for the user.
The fundamental problem is that every attribute you standardize reduces uniqueness but also potentially breaks websites that depend on accurate information about your environment.
How much entropy does your browser leak?
If you're curious about what your specific browser exposes, I built a fingerprint checker at zovo.one/free-tools/browser-fingerprint-checker that shows you the individual signals, their entropy contribution, and how unique your combination is.
Browser fingerprinting works because the web platform was designed to give websites information about your environment so they could render content correctly. Privacy and functionality pull in opposite directions. Knowing how fingerprinting works is the first step toward deciding where you fall on that trade-off.
I'm Michael Lip. I build free developer tools at zovo.one. 350+ tools, all private, all free.
Top comments (0)