Canvas Fingerprinting: How GPU-Rendered Signals Identify a Browser
How canvas fingerprinting works, what WebGL adds, why browsers randomize it, and how much entropy it really contributes — with code.
Canvas fingerprinting works because two machines drawing the same shapes produce different pixels. Instruct a browser to render identical text and graphics to an HTML5 <canvas>, read the result back, and the exact bytes vary from one machine to the next — because the GPU, graphics driver, font rasterizer, and anti-aliasing stack are all slightly different. Researchers demonstrated the effect in the 2014 "Web Never Forgets" study; what matters more is what the signal is worth in 2026. This article covers how the pixels are produced, what WebGL adds, how much entropy canvas actually contributes, and what browser randomization has done to it.
What Is Canvas Fingerprinting?
Canvas fingerprinting is a technique that identifies a browser by rendering graphics to an HTML5 canvas and hashing the pixel output, which varies subtly across GPU, driver, and operating system combinations. The same drawing instructions yield a stable, near-unique value on a given machine and a different one elsewhere.
It is one signal within browser fingerprinting, the broader practice of identifying a returning visitor from the characteristics their browser exposes. Canvas is prized because it needs no permission prompt, runs invisibly off-screen, and produces high entropy from a single API call.
How the Canvas Signal Is Produced
The mechanics are three steps. A script creates an off-screen canvas, draws a mix of text and shapes to it, then reads the pixels back — usually with toDataURL(), which returns a Base64-encoded PNG, or getImageData() for the raw pixel array. That output is hashed into a compact identifier.
The interesting part is why the output varies at all when the instructions are identical. Several layers of the rendering stack each leave a mark:
GPU and graphics driver. The hardware and its driver decide how vectors become pixels. Different silicon and driver versions round differently.
Font rasterization and hinting. Turning a glyph outline into pixels depends on the font engine, installed fonts, and hinting settings, which differ by OS and version.
Anti-aliasing and sub-pixel rendering. The smoothing applied to edges and the sub-pixel geometry vary by platform, producing different intermediate colour values along every curve.
Colour profile and OS compositing. The system colour profile and the compositor that flattens the canvas can shift channel values by a bit or two.
None of these differences is visible to a person — they are single-bit variations across a handful of pixels. But a hash amplifies any difference into a completely different output, so a one-bit change produces an entirely distinct fingerprint. That sensitivity is what makes canvas both useful for identification and fragile under the randomization defences covered below.
WebGL Fingerprinting: The Same Idea, More Hardware
WebGL fingerprinting applies the same read-back-and-hash approach to 3D rendering, and it is a stronger sibling signal because it exercises more of the graphics pipeline. Rendering a scene through WebGL touches shaders, floating-point math, texture handling, and depth calculations — a wider surface for hardware and driver differences to show up in than 2D canvas.
WebGL also exposes hardware identity more directly. The WEBGL_debug_renderer_info extension returns the unmasked GPU vendor and renderer strings — values like the exact graphics chip and driver — which are high-entropy on their own, before any pixels are rendered. That directness is also why browsers have started restricting it: some now return generic strings or gate the extension, and privacy-focused browsers block it outright. The pixel-based WebGL signal, like canvas, is still collected by reading the rendered output back and hashing it.
How Much Entropy Does Canvas Actually Contribute?
Every article calls canvas "highly unique," but the honest framing is comparative: canvas is one high-entropy component among many, not an identifier on its own. A canvas hash narrows a visitor down considerably, but plenty of people share a hardware, driver, and browser combination that produces the same value. It is the combination of components that identifies, never a single one.
ThumbmarkJS makes this concrete. Its open-source library collects canvas alongside WebGL, audio, fonts, screen, hardware, and locale signals — the same set covered in our overview of browser fingerprinting techniques — then hashes them together. That combination reaches roughly 80% uniqueness across a large visitor population; adding server-side signals through the API raises it to around 99%. Canvas is one contributor to those figures, not the source of them — which is exactly why a fingerprint stays usable when any single component, canvas included, is weakened or missing. Treating a canvas hash as a visitor ID on its own is the mistake; treating it as one strong input into a combined fingerprint is correct.
Running across 60,000+ websites, that component mix also shows how the same signal can be both a hardware and a software artefact: canvas rendering is software, but the GPU and driver differences it captures are hardware. That blend is the crux of the distinction between browser and device fingerprinting — every one of these signals is read through the browser, so the identifier they combine into always resolves to a browser environment, not a bare device.
Canvas Fingerprinting Protection: Randomization, Blocking, and What Breaks
Browser defences fall into two mechanisms, and they break a fingerprint in different ways. An engineer collecting canvas needs to handle both:
Noise (randomization). The browser perturbs the pixel values on read-back, so the hash changes. If it changes on every read, canvas becomes useless for stability; if it is stable per site and per session, it still links within that session but not across sites.
Absence (blocking). The component returns nothing usable — a blank canvas, a uniform value, or a thrown error — so there is no signal to hash at all.
Where each browser sits as of 2026:
Chrome applies no canvas or WebGL randomization by default. Canvas remains a stable, high-fidelity signal for the large Chrome and Chromium-based share of traffic.
Brave randomizes canvas and WebGL output by default through "farbling" — noise derived from a seed that changes per session and per site (eTLD+1). Because poisoning one component disrupts a combined hash, this is deliberately disruptive. Brave also blocks the
WEBGL_debug_renderer_inforenderer strings.Firefox injects random data into canvas read-back when
privacy.resistFingerprinting(RFP) is enabled. RFP is off in standard browsing but active in private windows and strict mode, and Firefox's default protection also blocks known fingerprinting scripts from a curated list.Safari has concentrated its anti-fingerprinting work on other surfaces, so canvas output stays comparatively stable; its protections lean on limiting known trackers rather than broadly randomizing canvas.
Tor Browser builds on Firefox RFP and is the strictest: it prompts before allowing canvas read-back and returns blank data by default.
Extensions such as Canvas Blocker add randomization or blocking on top of any browser. The practical takeaway is that a meaningful minority of traffic — privacy-focused browsers and extension users — will return noised or absent canvas values. A well-built fingerprinting library handles this by degrading rather than failing: when canvas is unstable or missing, it falls back on the remaining components instead of producing no fingerprint at all.
Should You Still Collect Canvas in 2026?
Yes, with caveats. For the large majority of visitors — Chrome, Chromium-based browsers, and default Safari — canvas is still a high-entropy, low-cost signal that meaningfully improves fingerprint uniqueness. Dropping it would weaken identification for most of your traffic to defend against a smaller privacy-conscious slice.
The caveats are firm. Canvas must never be a single point of identification: use it as one component in a combined fingerprint, so that a randomized or blocked canvas degrades accuracy rather than breaking recognition. And it needs a stability strategy for randomizing browsers — detecting when a component is producing noise and excluding it rather than letting it poison an otherwise stable fingerprint. For high-stakes decisions such as payment or login risk, this is also why server-side signals matter: they add entropy that no client-side randomization can touch.
Collecting Canvas and WebGL in Practice
A raw canvas hash is a short piece of vanilla JavaScript. This illustrates the mechanism — draw, read back, hash — and is not production-grade: it has no fallback for randomization and no error handling.
// Illustrative canvas fingerprint — draw, read back, hash. Not production-grade.
function canvasHash() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = "16px 'Arial'";
ctx.fillStyle = '#f60';
ctx.fillRect(10, 10, 100, 30);
ctx.fillStyle = '#069';
ctx.fillText('Canvas fingerprint 🖐', 12, 15);
const data = canvas.toDataURL(); // Base64 PNG of the rendered pixels
let hash = 0;
for (let i = 0; i < data.length; i++) {
hash = (hash << 5) - hash + data.charCodeAt(i);
hash |= 0; // force 32-bit integer
}
return hash.toString(16);
}In production you want the canvas signal collected, stabilized, and combined with the other components rather than used alone. ThumbmarkJS returns it as one entry under result.components, so you can read the canvas and WebGL values directly while the library handles hashing and fallback:
// The same signal in context, via the ThumbmarkJS open-source library
import { Thumbmark } from '@thumbmarkjs/thumbmarkjs';
const tm = new Thumbmark();
const result = await tm.get();
result.thumbmark; // combined fingerprint hash
result.components.canvas.commonPixelsHash; // the canvas component value
result.components.webgl.commonPixelsHash; // the WebGL component value
// get() never throws — check result.error for component failuresThis page covers the technique; for a full walkthrough of wiring a fingerprint into a real flow, see our guide to implementing browser fingerprinting in JavaScript, which owns the build end to end.
Conclusion
Canvas is a strong entropy contributor, not an identity. Its value in 2026 depends entirely on how you handle randomization: collect it as one component among many, detect when a browser is noising or blocking it, and fall back on the rest of the fingerprint rather than trusting a canvas hash on its own. Do that, and canvas remains one of the most useful low-cost signals available in the browser.
To see your own canvas and WebGL components inside a real fingerprint, see your own fingerprint components in the live demo, or read the collection code in the open-source library on GitHub.
Frequently Asked Questions
Is canvas fingerprinting legal?
It depends on jurisdiction and purpose. Under GDPR and ePrivacy rules, reading fingerprinting signals is generally treated like other access to a user's terminal equipment and may require consent depending on how the data is used — fraud prevention and advertising are treated differently. This is implementation- and jurisdiction-specific; review your use case with counsel rather than relying on a general rule.
Can canvas fingerprinting be blocked?
Yes. Browser settings (Brave, Firefox RFP, Tor, and to a lesser extent Safari) and extensions like Canvas Blocker either randomize the output or block it. Randomizing changes the hash so it can't be matched reliably; blocking removes the signal entirely. Both are handled by falling back on the fingerprint's other components.
Does canvas fingerprinting work in incognito or private mode?
Yes. Canvas reads rendering output, not stored data, so a private or incognito window does not remove it — which is precisely why it differs from cookies. Note that Firefox and Tor apply stricter canvas randomization in private mode, so the value may be noised even though the technique still runs.
Is a canvas fingerprint unique to my device?
No. It reflects a browser, GPU, driver, and OS combination, and many people share common hardware and browser setups that produce the same hash. On its own a canvas value is not identifying; it contributes entropy to a combined fingerprint that identifies a browser environment, never a device or a person.
What's the difference between canvas and WebGL fingerprinting?
Both measure GPU rendering, but canvas uses the 2D rasterization output while WebGL exercises the 3D pipeline and can additionally expose GPU vendor and renderer strings directly. WebGL generally carries more entropy; canvas is cheaper and more widely available.