one WebGL clear reads back as exactly one colour
Check id webgl-readback-flat-uniform
What an ordinary browser yields
One clear produces one distinct colour across every pixel read back — whatever byte value the driver settles on.
What a detector infers
A single glClear writes one colour into every pixel of the framebuffer, so reading that framebuffer back must yield exactly one colour. The value is deliberately never asserted — only that there is one of it. That matters, because drivers legitimately differ in how they convert a floating-point clear colour into bytes, and asserting the byte value would require a table of what each driver does; asserting uniformity requires nothing at all and cannot go stale. This is the WebGL counterpart of the 2D flat-fill check, and it earns its place next to the existing draw-path invariance check rather than duplicating it. That check compares the fixed-function clear path against a fragment shader painting the same colour, byte for byte — which means a perturbation applied equally to both readbacks cancels out of the comparison. Both paths can be noisy and still agree with each other perfectly, and on the browser measured here they do exactly that: draw-path invariance passes while neither path is uniform. Uniformity within a single readback has nothing to cancel against. Measured on a shipping stealth browser: one clear read back as five to six distinct colours over 4096 pixels. A 2×2 sample of that same framebuffer read back clean on every launch, which is the same undersampling trap the 1×1 canvas probe falls into and the reason the area is part of the method rather than an implementation detail.
How to resolve it
The framebuffer after a clear holds a single colour by construction, so several colours in the readback were introduced on the way out. Perturbing WebGL readback defends against GPU-render fingerprinting, which is a real thing to want to defend against; the observation here is only that sparsity, which is what keeps the perturbation visually and functionally harmless, is also what lets it survive small samples and cancel out of path-comparison checks while remaining obvious to a uniformity test over a large area.
Read in the wild by
CloakBrowser (measured)
A single clear to an opaque colour read back as five to six distinct colours over 4096 pixels, on every launch measured, with roughly eight pixels displaced by one unit per channel. The same framebuffer sampled 2×2 read back clean every time. The existing draw-path invariance check passed throughout, because the clear path and the shader path receive the same perturbation at the same offsets and therefore still match each other.
clearColor(1, 0.4, 0, 1) over 64×64 read back as 5, 6 and 5 distinct colours on three launches (dominant 4088/4088/4087 px, strays such as 254,102,0 and 255,103,1); 2×2 readPixels returned a clean 255,102,0,255 on 3/3. Stock Chrome and Clearcote on the same machine: exactly 1 distinct colour.
CloakBrowser (measured)Every attribution traces to a published artifact. See the sources and their limits.
Nearby checks in Render & GPU
- 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. - one pixel reads the same through a full read and a windowed read
canvas-subrect-consistencyThe 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… - 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… - 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… - canvas measureText widths on the 1/512 sub-pixel grid
measuretext-gridChrome's 2D text metrics are quantised: advance widths are computed in fixed-point and land on a dyadic 1/512-pixel grid. - text metrics are not a uniform multiple of the engine's own grid
text-metrics-uniform-scaleThis is the sub-pixel grid check asked one question deeper. That check reports THAT widths have left Blink's 1/512-pixel grid; this one asks…
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 webgl-readback-flat-uniform belongs to.