Back to blog
fingerprintingcanvas

Canvas fingerprinting, explained

How the HTML5 canvas becomes a tracking signal, why the same code renders differently across devices, and how to keep canvas output consistent per identity.

VTVeilBrowser Team2 min
Canvas fingerprinting, explained

TL;DR

Canvas fingerprinting asks your browser to draw text and shapes, then hashes the pixels. Tiny differences in GPU, drivers, fonts and anti-aliasing make that hash device-specific. A good defense produces a stable canvas hash per profile โ€” not a new one each visit.

The HTML5 <canvas> element lets a page draw graphics with JavaScript. It is also one of the most reliable fingerprinting surfaces on the web.

The same canvas draw producing different pixels per device

How it works

A script draws some text and shapes to an off-screen canvas, then calls toDataURL() (or reads pixels via getImageData()) and hashes the result:

canvas-probe.js
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
ctx.textBaseline = "top";
ctx.font = "16px 'Arial'";
ctx.fillText("VeilBrowser ๐Ÿ˜ƒ", 2, 2);
const hash = await sha256(canvas.toDataURL());

The exact pixels depend on the GPU, graphics drivers, installed fonts, sub-pixel anti-aliasing and the OS text renderer. Two machines rarely produce identical output, so the hash acts as a stable identifier.

Why it is so effective

  • It runs silently and quickly, with no permission prompt.
  • The output is stable across sessions on the same device.
  • It combines with other signals (WebGL, fonts) to raise uniqueness sharply.

What bad spoofing looks like

Two failure modes stand out:

  1. Per-request randomization. If the canvas hash changes every visit, the site sees an "impossible" device and flags it. Real devices do not do this.
  2. Inconsistent noise. Adding noise that does not match the claimed platform (for example, macOS anti-aliasing on a Windows user-agent) is a giveaway.

What good control looks like

The right approach is deterministic per profile: the canvas is controlled at the browser level so a given profile renders the same output every time, consistent with its platform, GPU and fonts. Across profiles the output differs โ€” as different devices would โ€” but within a profile it is rock-steady.

That is how VeilBrowser handles canvas: see the fingerprint engine and profiles.

FAQ

Try it

Spin up profiles with stable, platform-consistent canvas output. Start free or read the docs.

Related posts