reading the same framebuffer twice returns the same bytes
Repeated readPixels of one unchanged framebuffer return identical bytes. Brave's stock farbling makes them differ and is declined rather than scored.
What a detector infers
The same assertion as the canvas row beside it, asked one layer down the graphics stack, and separate from it because a build can be deterministic in one path and not the other. A glClear paints a single colour into every pixel of the framebuffer, so reading that framebuffer back twice with nothing drawn in between must return identical bytes — the buffer cannot hold two values. Any difference was introduced on the way out, by a readback path that perturbs per call.
The value of the clear colour is deliberately never asserted, only that repeated reads agree, which keeps the check independent of how a given driver converts a float clear colour to bytes.
How to resolve it
Seed WebGL readback noise per session rather than per call. If the 2D canvas path is already deterministic and this one is not, the noise is being applied at the GL readback layer specifically.
Nearby checks in Render & GPU
- one canvas encodes the same pixels through toBlob and toDataURL
canvas-toblob-vs-todataurlA canvas has three exits — getImageData, toDataURL and toBlob — and a build that perturbs canvas readback has to perturb all three… - the WebGL2 element-count limits are reported beside the renderer that claims them
webgl-max-elements-readoutMAX_ELEMENTS_INDICES and MAX_ELEMENTS_VERTICES are hints the driver publishes about how many indices and vertices it draws efficiently in… - the WebGPU preferred canvas format is reported beside the claimed platform
webgpu-canvas-format-readoutnavigator.gpu.getPreferredCanvasFormat() returns the texture byte order the platform's compositor wants to be handed — and that preference… - drawing the same scene twice produces the same pixels
canvas-repeat-render-determinismCanvas noise is usually reasoned about as a trade: give up a stable hash, gain an unlinkable one. - MathML scripts are shaped with real metrics, not flattened to text
mathml-metrics-vs-osMathML metrics sit in the long tail of a deployed collector's signal inventory, read through an <mmultiscripts> element. - a hidden child realm lays text out exactly as the page does
hidden-iframe-layout-agreementA deployed commercial agent does not run most of its collectors in the page. - the time a hidden frame takes to be created and measured in is reported
hidden-iframe-completion-budgetThe second failure mode of the hidden-frame modality, and one nothing in this audit could previously report: not a wrong answer, but no… - GPU-side pass timing is reported beside the wall clock
webgpu-timestamp-vs-wallclockA deployed commercial agent's GPU collector is not a pixel hash.
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-repeat-readback-determinism belongs to.
