Back to all posts

Detection · Sep 25, 2026 · 5 min read

Canvas fingerprinting: why 5 profiles on one machine share a hash

What canvas fingerprinting reads, which parts of a machine decide the hash, and why browser profiles on one computer share it without looking fake.

DG
Pixel art of a still mountain lake at blue hour with small wooded islands mirrored perfectly in the water

In short

Canvas fingerprinting draws text and shapes into a hidden canvas, reads the pixels back and hashes them, and the result describes the graphics card, driver, fonts and browser rather than the user. Profiles on the same machine therefore share one canvas hash: in our July 2026 test, 5 profiles with honest readback produced 1 hash. A shared value is ordinary, because every machine with the same hardware draws it too; noise that made all 5 unique was flagged as manipulated.

Teams that run several browser profiles for their agents on one computer usually ask the same question about canvas: if every profile produces the same hash, will a site link them? It helps to know what the hash describes before deciding that it should differ. Canvas fingerprinting measures the machine that draws, and a machine draws the same way for every profile on it.

What is canvas fingerprinting?

Canvas fingerprinting is a technique in which a page draws text and shapes into an HTML canvas it never shows, reads the resulting pixels back and turns them into a short hash. Keaton Mowery and Hovav Shacham described it in 2012 in "Pixel Perfect: Fingerprinting Canvas in HTML5", using the two read-back paths that are still the usual ones: getImageData(), which returns the RGBA values of every pixel, and toDataURL("image/png"), which returns the whole canvas as an encoded PNG. Their summary of why it works is the key to everything below: the pixmap "(and therefore its hash) will be identical in multiple runs on one machine, but take on different values depending on hardware and software configuration."

The technique fits in a few lines, and the hash at the end is all a site needs to store:

js
const canvas = document.createElement("canvas")
const ctx = canvas.getContext("2d")
ctx.textBaseline = "top"
ctx.font = "16px Arial"
ctx.fillStyle = "#f60"
ctx.fillRect(0, 0, 120, 20)
ctx.fillStyle = "#069"
ctx.fillText("Cwm fjordbank glyphs vext quiz", 2, 2)
const bytes = new TextEncoder().encode(canvas.toDataURL("image/png"))
const hash = await crypto.subtle.digest("SHA-256", bytes)

Which parts of the machine decide the canvas hash?

The canvas hash is decided by the software and hardware that turn drawing commands into pixels, not by anything the user typed or set. Mowery and Shacham read it "as evidence that a user is running some particular configuration of browser, operating system, graphics driver, GPU", and five parts carry that configuration:

  • The graphics card does the rasterisation when the browser draws on the GPU, and two models round edges differently.
  • The graphics driver sits between the browser and the card, and a driver update can change pixels on the same card.
  • The font rasteriser and the installed fonts decide how a glyph lands on the pixel grid; the paper's own tests draw text for exactly that reason.
  • Anti-aliasing and subpixel settings blend the edges of text and curves, and they follow operating system settings.
  • The browser and its version decide which drawing path and which defaults are used.

In the paper's sample of 294 experiments on Amazon Mechanical Turk, the authors observed 116 distinct values, a sample entropy of 5.73 bits. That is high enough to separate many users, and it also means that many different people shared a value, which is why browser fingerprinting combines canvas with other values.

Why do profiles on one machine share a canvas hash?

Profiles on one machine share a canvas hash because they share the card, the driver, the fonts and the browser build that draw it. A profile changes cookies, logins and the values a browser is told to report; it does not change how the machine rasterises a line of text. The shared value is also not unusual on the web, because every other machine with the same hardware and drivers produces it as well. We tested this on one machine with five profiles.

Canvas readbackDistinct hashes across 5 profilesWhat a page reads
Offset of up to 2 per channel, seeded per profile5 of 5a value no device draws, flagged as manipulated
Honest device value1, shared by all 5the value this card and driver draw
Source: Scalebrowser engine, canvas readback on one machine, 5 profiles, July 2026

What happened when noise made each profile unique?

Each profile got its own canvas hash, and a public checker marked the canvas as manipulated, because a small offset on every pixel puts variation into flat areas that a graphics card draws as one colour. The full measurement, and the same effect on pointer movement, is in the write-up on why adding noise is the tell. Browsers that add noise on purpose say so openly: MDN's page on getImageData() notes that with fingerprinting protection "random subtle noise is introduced", so that putImageData() and getImageData() "may not round-trip". A page can test exactly that by drawing once and reading twice. Some automation browsers switch such noise on by default, and the CloakBrowser review shows one whose own troubleshooting table names "Noise injection detected by ML" as a reason for being flagged.

Is audio readback read the same way?

Yes. An audio fingerprint renders a short signal offline and reads the samples back, the same pattern as canvas with sound instead of pixels. In the Scalebrowser engine, canvas, WebGL, WebGPU, measureText and audio all report what the device produces, with no added noise.

How does WebGL differ from 2D canvas?

WebGL adds a second, direct channel: besides reading pixels back, a page can ask the context for the renderer and vendor strings. Mowery and Shacham already noted in 2012 that browsers redact these strings, and concluded that "browser vendors consider hardware and driver version to be identifying information." Wherever a browser does report the real renderer, the string and the pixels have to describe the same card.

What should you check in your own automation stack?

Check whether your canvas hash matches the one your everyday Chrome produces on the same machine, and whether two reads of the same drawing return the same value. A match on both is the ordinary case. A value that changes between reads, or one that no other browser on that hardware produces, is the case a site notices. The profiles page of our documentation describes which values a Scalebrowser profile takes from the machine instead of inventing them.

Run it on your own machine

Seven days to try it with your own agents on your own sites. Starting the trial needs a card.

Start the 7-day trial
DG

Davide Grasböck

Founder, Scalebrowser

Builds Scalebrowser, the browser layer for AI agents that runs on your own machine. Measures every change a web page could observe against a real browser before it ships, and writes up the ones that turned out wrong.