one pixel reads the same through a full read and a windowed read
Check id canvas-subrect-consistency
What an ordinary browser yields
Every pixel in the overlap reads identically through the full-canvas read and through the smaller windowed read.
What a detector infers
The same pixels, asked for twice through different windows. A full-canvas read and an inner 16×16 read overlap on 256 pixels, and those are literally the same pixels of the same untouched bitmap, so the two answers have to carry the same bytes. What makes this the most general of the canvas rows is that it asserts nothing whatsoever about what the canvas ought to contain — no fill colour, no reference image, no expected hash. It only requires the browser to agree with itself about one region it has already stored. The scene drawn here is deliberately non-uniform, a gradient with a rectangle over it, precisely so that this cannot be a restatement of the flat-fill check. What it catches specifically is a perturbation indexed by offset within the RETURNED BUFFER rather than by position on the canvas. When the noise is addressed that way, moving the requested rectangle moves the noise with it, and a pixel near the middle of the canvas gets one value when it arrives at buffer offset 4180 and a different value when the same pixel arrives at offset 136 of a smaller window. Measured on a shipping stealth browser: fourteen to eighteen channel readings out of 1024 changed value between the two reads, on every launch. This also explains why the obvious defence fails. Reading the same rectangle twice returns identical bytes, because the offsets are identical, so a re-read test sees nothing; it is only when the WINDOW changes that the addressing shows itself.
How to resolve it
getImageData hands back a copy of a region of one bitmap, and asking for a smaller region cannot change what is stored there. A modification written into the returned buffer and indexed by position within that buffer travels relative to the canvas whenever the requested rectangle moves, which is what makes one pixel disagree with itself. Indexing the perturbation by canvas coordinates instead removes this particular contradiction — though the flat-fill row still sees the noise, because that one does not depend on addressing at all. Not scored for Brave, which ships canvas farbling as a stock privacy feature.
Read in the wild by
CloakBrowser (measured)
Reading the same 256 pixels through a 16×16 window instead of through the full canvas changed fourteen to eighteen of the 1024 channel readings, on every launch measured. Re-reading the identical rectangle produced identical bytes, so the noise is not per-call randomness — it is addressed by offset within whatever buffer is returned, which is why only changing the window exposes it.
16, 14 and 18 mismatched channel readings of 1024 compared, on three launches, against a gradient scene. Re-read of the same rectangle: 0 differing bytes. Stated at its cleanest on a flat fill: of the pixels that deviate in a 32x32 read, 0 land at the same canvas coordinates as those deviating in the full 64x64 read, on 2/2 launches — changing the requested rectangle relocates the perturbation completely. Six other export paths (toDataURL, toBlob+createImageBitmap, createImageBitmap, transferToImageBitmap, putImageData round-trip) all reproduce getImageData exactly, so there is no route that avoids it. Stock Chrome and Clearcote on the same machine: 0 mismatched of 1024.
CloakBrowser (measured)Every attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Render & GPU
- masked WebGL VENDOR matches the engine
webgl-engine-vendorThis check reads the plain gl.getParameter(gl.VENDOR) — the masked value, not the debug extension's unmasked GPU string. - WebGL1 and WebGL2 report the same UNMASKED GPU
webgl1-webgl2-coherenceThe check creates a WebGL1 context and a WebGL2 context and reads UNMASKED_VENDOR_WEBGL / UNMASKED_RENDERER_WEBGL from each through the… - canvas readback is not noise-injected (1×1 probe)
canvas-tamperThe probe fills a single pixel with pure black on a 1x1 canvas and reads it straight back with getImageData. - one flat fill reads back as exactly one colour
canvas-flat-fill-uniformThis is the area form of the 1×1 canvas probe, and it exists because that probe is easy to pass by accident. - a canvas reads back the same through toDataURL and getImageData
canvas-todataurl-vs-getimagedatatoDataURL and getImageData are two exits from one canvas, and PNG is lossless, so decoding the data URL back into pixels has to reproduce… - one WebGL clear reads back as exactly one colour
webgl-readback-flat-uniformA single glClear writes one colour into every pixel of the framebuffer, so reading that framebuffer back must yield exactly one colour. - a WebGL framebuffer reads back the same through readPixels and toDataURL
webgl-readpixels-vs-todataurlreadPixels and toDataURL both read the drawing buffer of one WebGL canvas, and PNG is lossless, so decoding the data URL has to reproduce… - WebGL and WebGPU agree on whether this device clears uniformly
webgl-webgpu-readback-agreeOne clear, two GPU APIs, one adapter. WebGL paints a flat colour and reads it back with readPixels; WebGPU renders the same clear into a…
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-subrect-consistency belongs to.