Browsers do not all offer the same features, and some privacy-focused browsers deliberately blur certain measurements. WhiskerJS works in all of them: it always returns all 46 components, each with a status that says whether it was read, missing, or left out on purpose. The pages below explain, for each browser family, what WhiskerJS can read, what the browser blocks, and what the library skips so that your ids do not fill with noise.
Browser classes
Before it collects anything, WhiskerJS sorts the browser into one of six classes, using cheap hints that never prompt: navigator.brave, the user agent, navigator.vendor and, for Firefox, a set of resistFingerprinting traits. The checks run in this order, and the first match wins:
brave:navigator.brave.isBraveis a function.firefox_rfporfirefox: the user agent has aFirefox/<number>token, or the window hasmozInnerScreenX. It isfirefox_rfponly when every resistFingerprinting trait holds at once (see Firefox resistFingerprinting and Tor Browser).chromium: the user agent has aChrome/<number>orChromium/<number>token, orwindow.chromeexists and the vendor isGoogle Inc..safari: the vendor isApple Computer, Inc., or the user agent has bothSafari/andVersion/.other: anything else, for example a headless Chromium whose user agent saysHeadlessChromeand which has nowindow.chrome.
The class does two things. It is reported as the browser_class component (part of the visitorId), and it picks the row of the exclusion table. It is a guess from values the client controls, so your server should treat it as a hint.
The nine browser families
| Family | Class | Excluded components | Page |
|---|---|---|---|
| Chrome (desktop) | chromium |
none | Chrome desktop |
| Chrome on Android | chromium |
none | Chrome Android |
| Safari on macOS | safari |
none | Safari macOS |
| Safari and every iOS browser | safari |
none | Safari and iOS browsers |
| Firefox | firefox |
none | Firefox |
| Firefox resistFingerprinting and Tor Browser | firefox_rfp |
9 | Firefox RFP and Tor |
| Brave | brave |
7 | Brave |
| Microsoft Edge | chromium |
none | Edge |
| Samsung Internet | chromium |
none | Samsung Internet |
Four kinds of “missing”
A component that is not ok always says why, with a status and a ruleId. Across browsers you will mostly meet four cases:
- The API does not exist here:
unavailablewith ruleIdno_api. Example:device_memoryin Safari and Firefox, because only Chromium-based browsers offernavigator.deviceMemory. - WhiskerJS skips it here on purpose:
unavailablewith ruleIdskipped. Onlyaudio_latencydoes this, outside Safari and Android, to avoid a console warning. - The browser blurs it on purpose:
excludedwith ruleIdbrave_farblingorfirefox_rfp, from the exclusion table. - The browser or an extension adds noise this time:
noisywith ruleIdrender_mismatch, when the double render ofcanvasorwebgl_imagediffers.
Every non-ok status counts the same in the visitorId (as “missing”), so a component that is blocked in one run and timed_out in the next does not change the id. See Statuses and reason codes.
How much is measured
Very little so far, and this section says so plainly. The support matrix is filled from the library code and documentation. The only real observations are an early, small sample at signalsVersion 1, not a benchmark: Mac Chrome (4 runs), Mac Safari (2 runs), iPhone Chrome (3 runs) and iPhone Safari (3 runs) each kept one id across their runs, the four ids differed from each other, and device_memory was unavailable on Safari and iOS. No head-to-head measurement against other libraries has run.
You can measure your own devices with the lab mode of the live demo.
Questions and answers
Does WhiskerJS work in every browser?
collect() runs and resolves in every browser, because each component reports a status instead of failing. What differs is which components are ok: some APIs exist only in Chromium-based browsers, and some components are excluded on purpose in Brave and in Firefox with resistFingerprinting.
Why is Chrome on iPhone treated like Safari?
On iOS every browser uses Apple's WebKit engine. Chrome, Firefox and Edge on iOS report the Apple vendor string and no Chrome/ token in the user agent, so WhiskerJS classes them as safari.
Is the browser support table measured?
Mostly not yet. It is filled from the library code and documentation, plus one early lab sample of four device and browser pairs at signalsVersion 1. It will be refreshed from aggregated diagnostics later.