Deleting cookies no longer prevents tracking. Fingerprinting identifies your browser by its technical characteristics — the GPU, installed fonts, how the audio engine responds — building a footprint that is never stored on your device and therefore cannot be deleted. Understanding how it is computed is the first step to knowing how exposed you are.
What a fingerprint consists of
A fingerprint is the combination of dozens of values your browser voluntarily hands to any script. Individually, each one is harmless and even useful (developers need them to adapt the experience). Combined, they form a surprisingly unique identifier.
The classic signals, grouped by origin:
From the navigator object: full user-agent, preferred languages, CPU core count (hardwareConcurrency), approximate memory (deviceMemory), touch support (maxTouchPoints), whether cookies are enabled.
From the screen: resolution, color depth, device pixel ratio. A MacBook with a Retina display and a PC with a 1440p monitor do not share these values.
From your environment: time zone via Intl.DateTimeFormat().resolvedOptions().timeZone. Europe/Madrid versus Atlantic/Canary already rules out entire regions.
Canvas fingerprinting: the imperfect-pixel trick
The most famous signal exploits the fact that two GPUs never draw exactly alike. The technique draws something complex onto a hidden canvas and extracts the result as an image:
const canvas = document.createElement("canvas");
canvas.width = 240;
canvas.height = 60;
const ctx = canvas.getContext("2d");
ctx.fillStyle = "#f60";
ctx.fillRect(0, 0, 240, 60);
ctx.fillStyle = "#0f0";
ctx.font = "16px Arial";
ctx.fillText("MACM fingerprint", 4, 22);
ctx.strokeStyle = "rgba(102, 204, 0, 0.7)";
ctx.beginPath();
ctx.arc(120, 30, 20, 0, Math.PI * 2);
ctx.stroke();
const data = canvas.toDataURL();
That same instruction sequence produces slightly different pixels depending on GPU, drivers, OS and antialiasing/typography settings. The result (toDataURL) is reduced with a fast hash — typically 32-bit FNV-1a, sufficient because it only needs comparison, not protection:
function fnv1a(str) {
let h = 0;
for (let i = 0; i < str.length; i++) {
h = ((h << 5) - h + str.charCodeAt(i)) | 0;
}
return h >>> 0;
}
Even the dataURL length adds extra information. Two identical factory machines can be distinguished because their driver versions differ.
WebGL and audio: hardware confessing
WebGL goes beyond 2D canvas: through the WEBGL_debug_renderer_info extension the browser reveals your graphics card's real vendor and renderer — literally the GPU model. It is one of the highest-entropy signals available, and it also allows test renderings whose output varies between chips.
Audio uses the Web Audio API cleverly: it processes a tone through a dynamic compressor in an offline context and measures the resulting values:
const ctx = new OfflineAudioContext(1, 5000, 44100);
const osc = ctx.createOscillator();
osc.type = "triangle";
osc.frequency.value = 10000;
const comp = ctx.createDynamicsCompressor();
comp.threshold.value = -50;
comp.knee.value = 40;
comp.ratio.value = 12;
osc.connect(comp);
comp.connect(ctx.destination);
osc.start(0);
const buffer = await ctx.startRendering();
let sum = 0;
for (let i = 4500; i < 5000; i++) {
sum += Math.abs(buffer.getChannelData(0)[i]);
}
The sample sum (to 8 decimal places) differs minutely between each browser/platform's floating-point audio implementations. Invisible to users, stable over time, impossible to "delete".
Installed fonts: measuring the invisible
Font detection exploits a rendering property: if you request text in a font that does not exist, the browser substitutes it. Measuring rendered text width reveals which ones you have installed. The classic method compares the width of the same string in the candidate font versus two generic base fonts:
function detectFont(candidate) {
const testString = "mmmmmmmmmmlli WWWW@#%";
const span = document.createElement("span");
span.style.cssText =
"position:absolute;left:-9999px;font-size:72px;white-space:nowrap;";
span.textContent = testString;
document.body.appendChild(span);
const widthWith = font => {
span.style.fontFamily = `${font}, monospace`;
return span.offsetWidth;
};
const baseMonospace = widthWith("__base__");
const candidateWidth = widthWith(candidate);
document.body.removeChild(span);
return candidateWidth !== baseMonospace;
}
If the width with Consolas, monospace differs from plain monospace, then Consolas exists and was used. Repeated against some 18-20 common fonts, the resulting set distinguishes Windows from Mac, and office from home.
From signals to hash: combining and quantifying
The final step concatenates all signals with a separator and computes a SHA-256 via WebCrypto:
const combined = [userAgent, languages, timezone, screen, ...].join("|");
const digest = await crypto.subtle.digest(
"SHA-256",
new TextEncoder().encode(combined)
);
const hex = [...new Uint8Array(digest)]
.map(b => b.toString(16).padStart(2, "0"))
.join("");
Over that set you estimate entropy in bits: each signal contributes according to how many distinct values it has across the real population. A reasonable estimate sums about 55 nominal bits — equivalent to 2^55 ≈ 3.6 × 10^16 possible combinations. In practice effective entropy is lower because signals correlate (Safari users are probably on Macs), but it is enough for your specific combination to be unique among millions of visitors.
Honest nuance: those weights are nominal, assigned from prior knowledge of each signal's diversity. Measuring real entropy would require an enormous reference population.
Which defenses exist (and which don't)
What does NOT work: deleting cookies, incognito mode or changing IPs. The fingerprint lives in the browser, not on your machine.
What does help:
- Tor Browser actively normalizes signals: every user presents the same resolution, the same limited font set, noisy canvas. Its goal is making you indistinguishable from the crowd.
- Firefox with
privacy.resistFingerprintingapplies similar normalization (UTC time zone, canvas randomized per session). - JavaScript blockers reduce exposure: without JS, almost no signal can be collected.
- Private windows partially help: some browsers add canvas noise in incognito mode.
And the fundamental paradox: defending yourself in original ways makes you more unique. Installing uncommon anti-fingerprinting extensions or using exotic font configurations creates a new, even rarer fingerprint. Security here is statistical, not absolute: the goal is resembling as many people as possible.
Check your own fingerprint
Our Browser Fingerprint Test computes all of this live and 100% locally: the 11 signals, the combined SHA-256 hash and the uniqueness estimate. Nothing leaves your device — ironically, you will see your own fingerprint without showing it to anyone.
FAQ
Is fingerprinting legal? Depends on jurisdiction and use. European GDPR treats it as processing personal data when it identifies or makes a person identifiable, which requires informed consent. In practice many sites do it de facto without complying.
Does changing browsers change my fingerprint? Yes, completely: each browser exposes different signals. But within one browser, the fingerprint stays very stable for months.
Do VPNs protect against fingerprinting? No. A VPN changes your IP, which is precisely the one signal fingerprinting does not need.
Discover your own fingerprint with the Browser Fingerprint Test, computed entirely on your device.