Live demo · WhiskerJS 0.1.0

Your device, read by the real library

This page runs the WhiskerJS collector in your browser and shows exactly what it returns: the visitorId, the structured id with one short hash per signal group, every component with its status, and the integrity flags. Run it again, come back tomorrow, and see whether the id holds, and if it does not, which group moved.

Privacy: what happens on this page

  • What is collected: 46 browser and device signals (screen, languages, time zone, fonts, graphics and audio rendering, and similar). Large values such as images and font lists are reduced to a SHA-256 digest in your browser. Nothing asks for permission: it reads which permissions you have already granted or refused without requesting any. For a moment it also adds invisible test boxes (to see whether an ad blocker hides them) and one blank, invisible frame (to compare built-in functions against a clean copy), and removes them at once. No network addresses.
  • Nothing is sent without a lab key. For every visitor this demo makes no network requests: WhiskerJS has no network code, the page has no analytics or third-party scripts, and the page's security policy allows no outgoing connection except to OpenStake's own lab server. The one exception is lab mode with a lab key, which only OpenStake's own test devices have: it sends this device's lab results (device label, time, browser and OS, session, visitorId, structuredId with its group hashes, library versions and the names and statuses of components that were not ok; no component values) to OpenStake's own server, diagnostics.whiskerjs.com. Without a lab key the page sends nothing.
  • It stays on this device. The library stores nothing. This page keeps a history of your runs (time, id, structured id, versions and component values), your device label and a session counter in this browser's local storage, so it can show whether your id stays the same across visits.
  • Clearing it: press Clear my history below to remove everything this page stored, or clear this site's data in your browser settings.

Result

What WhiskerJS returned

Loading WhiskerJS...

visitorIdcollecting...
First run on this device
version
-
signalsVersion
-
idVersion
-
duration
-
components ok
-
session on this device
-

structuredId

one short hash per signal group, so two runs can be compared group by group
collecting...

    The format is the idVersion, then one 12-character hash for each group, joined by underscores. Each hash covers only that group's components, so a new GPU driver changes the gpu part and leaves the rest alone.

    Integrity flags

    signs of automation or tampering; WhiskerJS reports them, your server decides
      What every flag means

      Components

      Every component WhiskerJS reported, with what it measures, its status, the reason when it is not ok, whether it counts in the visitorId, and its value.
      ComponentStatusReasonIn idValue
      What the statuses mean
      ok
      The value was collected.
      unavailable
      The browser does not offer the API, or it gave nothing.
      blocked
      The API refused, threw an error or returned an empty result.
      noisy
      Two renders differed: the browser adds random noise, so the value is left out.
      excluded
      Not collected, because this browser is known to fake or randomise it, or the page asked.
      timed_out
      It took longer than its time limit.

      This library version adds no new status, but it adds reason codes. The one you are most likely to see:

      skipped
      Shown as unavailable with this reason: WhiskerJS chose not to read the signal in this browser. audio_latency is only read in Safari and on Android, because elsewhere opening an audio device without a tap makes the browser print an autoplay warning. Nothing is wrong with your browser.
      unknown
      A component gave a reason WhiskerJS does not recognise, so it reports this one instead.

      Components marked new arrived with this library version. Some report a plain word instead of a measurement: none means nothing was found (no ad blocker, no Apple Pay), and canvas_readback reports exact when a test pixel reads back unchanged or altered when something adds noise to canvas reads. In ua_client_hints, he=blocked means the site's policy refused the detailed hints.

      "In id: yes" means the component is part of the visitorId. A component that is not ok still counts, as a fixed "missing" marker, so a signal that is blocked in one run and timed out in the next gives the same id. Digests are the first 128 bits of SHA-256, made in your browser.

      Stability

      This device, visit after visit

      Each run is kept in this page's own local storage on this device. The library stores nothing; the page does, so it can compare. Newest first, with the structuredId groups and the components that changed since the run before. Runs made with a different library version are never compared: a new version is expected to give a new id, so the list marks the boundary instead.

        Lab testing mode

        Measure it on your own devices

        1. Give this device a label, for example "Windows Chrome" or "iPhone Safari".
        2. Load the page three times on each device (reload it, or close it and open it again), and after each load press "Copy result line". With a lab key saved on this device, every run is sent to the lab log automatically instead.
        3. After a browser update, run it again on that device.
        4. Paste every line into one sheet. The lines are tab separated, so each value lands in its own column; "Copy header line" gives the column names.
        Remembered in this browser only.
        Session-Goes up by one each time the page loads.
        Only for OpenStake's own test devices. Kept in this browser's local storage only and never shown again. With a key and a device label, each run is sent to OpenStake's lab log.

        Result line preview. Browser and OS as this page detects them: -
        waiting for the first run...