---
title: "Canvas fingerprinting: why 5 profiles on one machine share a hash"
description: "What canvas fingerprinting reads, which parts of a machine decide the hash, and why browser profiles on one computer share it without looking fake."
canonical: "https://scalebrowser.net/blog/canvas-fingerprinting"
last_modified: "2026-09-25"
published: "2026-09-25"
author: "davide"
category: "detection"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://scalebrowser.net/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.

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](https://hovav.net/ucsd/dist/canvas.pdf)", 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](/blog/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.

<Evidence source="Scalebrowser engine, canvas readback on one machine, 5 profiles, July 2026">

| Canvas readback | Distinct hashes across 5 profiles | What a page reads |
| --- | --- | --- |
| Offset of up to 2 per channel, seeded per profile | 5 of 5 | a value no device draws, flagged as manipulated |
| Honest device value | 1, shared by all 5 | the value this card and driver draw |

</Evidence>

### 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](/blog/noise-is-the-tell). Browsers that add noise on purpose say so openly: MDN's page on [getImageData()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/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](/blog/cloakbrowser) 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](/docs/profiles) describes which values a Scalebrowser profile takes from the machine instead of inventing them.
