Skip to content
All fingerprint checksRender & GPU

one canvas encodes the same pixels through toBlob and toDataURL

Check id canvas-toblob-vs-todataurl

What an ordinary browser yields

toBlob and toDataURL decode to byte-identical pixels. One surface encoded twice is one image, on every engine.

What a detector infers

A canvas has three exits — getImageData, toDataURL and toBlob — and a build that perturbs canvas readback has to perturb all three identically or it contradicts itself. This audit already compares the first two. toBlob is the third, and it is worth asking separately because in a real engine it is a different code path from toDataURL: same surface, same encoder, different entry point. That is precisely the kind of seam where a patch gets applied in one place and missed in another, and the result is a canvas that hashes two different ways depending on which method a detector happens to call. The inference available to a detector is unusually strong, which is what makes this row worth its cost. It does not need to know what the correct pixels are, or hold any reference value, or know anything about the machine — it calls two methods on one canvas and observes that the browser gave two answers to one question. No amount of per-site seeding makes that legitimate. The comparison is done on decoded PIXELS rather than on the encoded bytes on purpose: two PNG encoders can legitimately differ in compression choices while painting identical images, and failing a browser for that would be exactly the false positive this audit takes most seriously.

How to resolve it

Apply canvas perturbation once, at a point every exit shares, rather than separately in each encode path. Per-exit seeding makes toDataURL, toBlob and getImageData drift apart, and that disagreement is self-evident to anyone who calls two of them — it needs no reference image to detect.

What is canvas fingerprinting?

Read in the wild by

CloakBrowser issues

A stealth-browser tracker records canvas readback differing between exits on one surface, and the resulting two-hashes-from-one-canvas signal.

CloakHQ/CloakBrowser #464, #294, #437 (canvas exit divergence)

CloakHQ/CloakBrowser#464

Clearcote (measured)

Confirmed non-accusatory on a stock browser before shipping: the same 40x20 surface encoded through both exits and decoded back gave byte-identical pixels, so the invariant this row asserts is one an unmodified engine actually holds.

stock desktop Chromium on Windows (ANGLE/D3D11, RTX 3070): 0 of 3200 channel bytes differed between toBlob and toDataURL

Every attribution traces to a published artifact. See the sources and their limits.

Nearby checks in Render & GPU

See all 38 checks in Render & GPU
Who builds this test

Clearcote is a browser built for fingerprint coherence

It is a Chromium fork, maintained by the same people who wrote this reference. It ships as a compiled browser rather than as a stealth script injected into someone else's — which is a description of how it is built, and is not an argument about how it behaves on this check.

This audit takes no position on how Clearcote scores on Render & GPU checks, on this one, or anywhere else. It has no baseline corpus of other people's fingerprints to rank you against and no vendor scoreboard — nearly every check is self-referential, asking one browser the same question through two independent APIs and reporting whether both answers can be true at once. It runs identically on any browser, including ours. Run it on yours and read the result yourself.

See the other checks in Render & GPU — the family canvas-toblob-vs-todataurl belongs to.