# Overview

> What WhiskerJS is, what it returns, and how to read the live demo.

Source: https://whiskerjs.com/docs/ (last updated 2026-10-26)

> **In plain words:**
>
> WhiskerJS is an open-source (Apache-2.0) script for web pages. It reads technical characteristics of the visitor’s browser and device, such as screen size, fonts and how a test image is drawn, and returns them as one JSON object. Your own server then decides what to do with it: recognise a device it has seen before, or notice that something looks automated. WhiskerJS itself never decides, never sends anything and never stores anything.

## What you get from one call

```ts
import { load } from 'whiskerjs';

const agent = await load();
const result = await agent.collect();
```

| Field | What it is |
| --- | --- |
| `components` | 46 measurements, each with a status (`ok`, `unavailable`, `blocked`, `noisy`, `excluded`, `timed_out`) and, when not ok, a reason code |
| `visitorId` | a 32-character hash of the 37 stable components: equal ids mean the same browser setup |
| `structuredId` | seven 12-character hashes, one per signal group, so two results can be compared group by group |
| `integrityFlags` | names of the 14 checks for automation and tampering that fired |
| `binding` | your server’s nonce and timestamp, bound to the result with a digest (only if you pass them) |
| `version`, `signalsVersion`, `idVersion` | `0.1.0`, `5`, `2`: store them with every id |
| `durationMs` | how long the collection took |

## What it is and is not

| WhiskerJS is | WhiskerJS is not |
| --- | --- |
| a collector of device and browser signals | a bot verdict or a risk score |
| a library that runs in your page | a hosted service or an API |
| stateless: every call starts from nothing | a tracker: it stores no cookie or id |
| silent on the network | telemetry: it never phones home |
| open source under Apache-2.0 | on npm yet (build it from source) |

## The pages

- [Getting started](https://whiskerjs.com/docs/getting-started/): Build it, add it to a page, collect once.
- [How it works](https://whiskerjs.com/docs/how-it-works/): The pipeline, timeouts, statuses, hashing, noise.
- [Signals](https://whiskerjs.com/docs/signals/): All 46 components and what they read.
- [Identifiers](https://whiskerjs.com/docs/identifiers/): visitorId, structuredId and comparing results.
- [Integrity checks](https://whiskerjs.com/docs/integrity/): 14 flags and their false positives.
- [Privacy](https://whiskerjs.com/docs/privacy/): What is and is not collected; the notice to give.
- [Integration](https://whiskerjs.com/docs/integration/): Your server, the onResult hook, anti-replay.
- [FAQ](https://whiskerjs.com/docs/faq/): Short answers to common questions.
- [API reference](https://whiskerjs.com/docs/api/): Every export, option and type.

## Reading the live demo

The [live demo](https://whiskerjs.com/demo/) runs the real library (the build of commit `1100e48`, signalsVersion 5, idVersion 2) in your browser and shows exactly what it returns. Nothing is sent anywhere; the demo page keeps a history of your runs in your own browser so it can compare them.

- **visitorId** (top left): the id for this browser setup. The chip under it says whether it matches your previous run on this device.
- **Version tiles**: `version`, `signalsVersion` and `idVersion` of the library, the run’s duration, how many components are `ok`, and how many times you have loaded the page.
- **structuredId**: the full value and one tile per group. After a second run, a group whose part changed is highlighted, which tells you *what* moved (for example `gpu` after a graphics driver update).
- **Integrity flags**: usually empty on a normal browser. “What every flag means” explains each one; see [Integrity checks](https://whiskerjs.com/docs/integrity/) for the false positives (privacy extensions often set `native_tampering`).
- **Components table**: every component with its status, the reason code when it is not ok, whether it counts in the visitorId, and its value. Values that are 32 hex characters are digests, not raw data. Common non-ok rows are normal: `device_memory` and `heap_limit` are `unavailable` outside Chromium-based browsers, `audio_latency` is `unavailable` with `skipped` outside Safari and Android, and under Brave several components are `excluded` with `brave_farbling`.
- **History**: newest first, with the groups and components that changed since the run before. Runs from different library versions are never compared; the list marks the boundary.
- **Lab testing mode**: label the device, load the page a few times, and copy one tab-separated line per run into a sheet to measure stability on your own devices. “Copy full JSON” includes the anti-replay binding (the demo makes its own nonce; a real site gets it from its server).

What to try: run it twice (the id should hold), open a private window (some browsers add canvas noise there, and `canvas` or `webgl_image` turn `noisy`), or change the browser language (usually only the `locale` part of the structuredId changes).
