| Component name | noise_profile |
|---|---|
| In the visitorId | no (reported, kept out of both ids) |
| structuredId group | none |
| Hashing | plain value; a digest only when longer than 128 characters or not printable ASCII |
| Excluded under | no browser class |
| Inner timeout | 1000 ms |
| Added in | signalsVersion 6 |
Some browsers add tiny random changes to what a page reads back from a canvas, a 3D drawing or a sound, so that those reads cannot be used to recognise the device. WhiskerJS draws three things whose exact result is known in advance (two colours on a canvas, one colour in WebGL, a constant level of sound), reads each twice and compares. The result says, for each of the three, whether the browser returned the exact answer, the same wrong answer twice, or a different answer each time. It describes the browser’s privacy settings, so it is kept out of the identifiers and is never treated as a sign of tampering.
What it reads
Three known-answer probes, each read twice. The value has the form canvas=<state>,webgl=<state>,audio=<state>:
- canvas: a 16x16 2D canvas, left half
rgb(17, 34, 51)and right halfrgb(204, 153, 102), read withgetImageData(). Every pixel must come back with exactly those bytes and alpha 255. - webgl: the collection’s shared 32x32 WebGL drawing buffer, cleared to
(51, 102, 153, 255)and read withreadPixels(). Every pixel must come back with those four bytes. - audio: an
OfflineAudioContext(1 channel, 1024 frames at 44100 Hz) rendering aConstantSourceNodeat 0.5, read withgetChannelData(0). Every sample must be exactly 0.5. Nothing is played and no audio device is opened.
How the technique works
- Each probe produces its known answer and reads it back twice.
- Both reads exact gives
exact. The same wrong answer twice givesseeded. Two different answers giveper_read. A probe that cannot run (no canvas, no WebGL, no offline audio, or an error) givesna. - The canvas and WebGL probes run once per collection, before the collectors, because their result picks the
firefox_fppandsafari_afpbrowser classes. The audio probe runs beside the collectors;noise_profilewaits at most 800 ms for it and reportsaudio=naafter that. - The same results are used by
canvas,webgl_imageandaudio: when their own render looks clean but the probe of the same API isseededorper_read, they reportnoisywith ruleIdseeded_noise.
The probes run for every collection except an aborted one, also when you exclude the components that use them.
Why it helps
Seeded noise is the same on every read within a session, so drawing the same scene twice cannot see it; only a comparison with a known answer can. Reporting which probes failed tells your server that a browser is privacy-hardened (Brave, Firefox Fingerprinting Protection, Safari Advanced Fingerprinting Protection, or a noise extension) and why some graphics or audio components are noisy.
Why it is not in the id
It describes the browser’s privacy settings and extensions, which users change. It is a browser trait, not an integrity flag: noise is a privacy choice, not tampering. Changing it never changes the visitorId or the structuredId.
Stability
Stable for a given browser and its settings. It changes when a protection mode or a noise extension is switched on or off, when a private window is opened (several browsers add noise only there), and audio can move between a state and na on a slow or busy device that misses the 800 ms wait.
Browser support and what blocks it
- Stock Chrome, Edge, Firefox and Safari:
canvas=exact,webgl=exact,audio=exactwhere WebGL and offline audio exist. - Brave, Firefox with Fingerprinting Protection and Safari with Advanced Fingerprinting Protection: typically
seededfor the APIs they randomise. - Without WebGL (turned off, blocklisted GPU, some containers):
webgl=na. - The component itself is always
ok; it is never excluded by a browser class.
Privacy
It reveals only whether the three reads are altered, which suggests a privacy setting or an extension. The test patterns are fixed and contain nothing about the page or the user. WhiskerJS does not try to work around the noise.
How WhiskerJS handles noise and failures
| Status | ruleId | When |
|---|---|---|
ok |
the three probe states, for example canvas=exact,webgl=na,audio=exact |
|
excluded |
caller_excluded |
you excluded it (the probes still run for the class and the other components) |
timed_out |
timeout, aborted |
the 1000 ms inner timeout, the overall budget or your abort signal |
A probe that fails reports na inside the value instead of a non-ok status. Never hashed.
Example value
A stock browser with WebGL and Web Audio:
"noise_profile": { "status": "ok", "value": "canvas=exact,webgl=exact,audio=exact" }
Questions and answers
What do exact, seeded, per_read and na mean?
exact: both reads gave the known answer. seeded: both reads gave the same wrong answer, which is noise seeded per session or per site (Brave, Firefox Fingerprinting Protection, Safari Advanced Fingerprinting Protection). per_read: the two reads differed, noise drawn on every read. na: the probe could not run here; audio is also na when its probe takes longer than 800 ms.
Is seeded noise a sign of fraud?
No. Noise is a privacy choice made by the browser or the user, not tampering, so it is reported here and never as an integrity flag. Read it as a trait of the browser's settings.
Why is noise_profile not in the visitorId?
It follows privacy settings and extensions, which users switch on and off. The components the noise affects (canvas, webgl_image, audio) turn noisy instead, which keeps the id the same from session to session.