Browsers · WhiskerJS 0.1.0

Browsers

What WhiskerJS reads in each browser family, what the browser blocks, and what the library leaves out on purpose.

In plain words

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:

  1. brave: navigator.brave.isBrave is a function.
  2. firefox_rfp or firefox: the user agent has a Firefox/<number> token, or the window has mozInnerScreenX. It is firefox_rfp only when every resistFingerprinting trait holds at once (see Firefox resistFingerprinting and Tor Browser).
  3. chromium: the user agent has a Chrome/<number> or Chromium/<number> token, or window.chrome exists and the vendor is Google Inc..
  4. safari: the vendor is Apple Computer, Inc., or the user agent has both Safari/ and Version/.
  5. other: anything else, for example a headless Chromium whose user agent says HeadlessChrome and which has no window.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: unavailable with ruleId no_api. Example: device_memory in Safari and Firefox, because only Chromium-based browsers offer navigator.deviceMemory.
  • WhiskerJS skips it here on purpose: unavailable with ruleId skipped. Only audio_latency does this, outside Safari and Android, to avoid a console warning.
  • The browser blurs it on purpose: excluded with ruleId brave_farbling or firefox_rfp, from the exclusion table.
  • The browser or an extension adds noise this time: noisy with ruleId render_mismatch, when the double render of canvas or webgl_image differs.

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.