Docs · WhiskerJS 0.1.0 · signalsVersion 5 · idVersion 2

Getting started

From the source code to a first result in your page.

In plain words

WhiskerJS is a small script you run in your web page. You call collect(), wait a moment, and get back one JSON object describing the browser and device: 46 measurements, two identifiers and a list of warning flags. You then send that object to your own server with a request you already make. The library is not on npm yet, so you build it from source first.

This page takes you from the source code to a first result in a page. It assumes you know how to run a JavaScript build and serve a web page.

1. Build the library

WhiskerJS is not on npm yet, and its source repository opens with the first public release. With the source in a folder named whiskerjs:

cd whiskerjs
pnpm install   # dev dependencies only: TypeScript and Node types
pnpm build     # writes dist/: ES2020 modules plus .d.ts type files
pnpm test      # optional: runs the test suite with node:test

Requirements: Node 18 or newer (tested on Node 22) and pnpm 10 (corepack enable gives you the pinned version).

2. Add it to your project

Pick one of these:

  • As a package. In the WhiskerJS folder run pnpm pack. It writes whiskerjs-0.1.0.tgz with dist/, LICENSE, NOTICE and THIRD_PARTY_NOTICES.md. In your project: npm install ../whiskerjs/whiskerjs-0.1.0.tgz (or the pnpm or yarn equivalent). Your bundler then resolves import { load } from 'whiskerjs'.
  • As plain files. Copy dist/*.js and dist/collectors/*.js (keep the folder layout) to your static files and load index.js as a module: <script type="module">import { load } from '/vendor/whiskerjs/index.js';</script>. This is how the live demo on whiskerjs.com runs it.

There are no runtime dependencies and no CDN.

3. Collect once

import { load } from 'whiskerjs';

const agent = await load();                 // cheap: no work happens yet
const result = await agent.collect();       // at most 5 s by default (1 s per component)

console.log(result.visitorId);              // '3feb3ead31e6b520459ad33ebc58f2d7'
console.log(result.integrityFlags);         // [] or e.g. ['automation_webdriver']

collect() never throws and never rejects, whatever the browser does. Collect in the browser, after the page has a <body>: several probes add hidden elements to the body for a moment, and without one they report unavailable.

The page must be a secure context (https, or http://localhost while developing). Hashing uses crypto.subtle, which browsers only offer there. Without it visitorId and structuredId are null and every large component reports unavailable with ruleId no_digest.

4. Read the result

for (const [name, c] of Object.entries(result.components)) {
  if (c.status === 'ok') console.log(name, c.value, c.hashed ? '(digest)' : '');
  else console.log(name, c.status, c.ruleId);
}
  • visitorId: one hash over the 37 stable components. Equal ids mean the same browser setup, as far as these signals can tell.
  • structuredId: seven short hashes, one per signal group, so you can see which part of a device changed. See Identifiers.
  • components: all 46, always present, each with a status. See Signals and How it works.
  • integrityFlags: names of checks that saw signs of automation or tampering. A hint for your server, not a verdict. See Integrity checks.
  • signalsVersion and idVersion: store them with every id; ids are only comparable within the same versions.

5. Send it to your own server

WhiskerJS has no network code. Add the result to a request you already make, for example the login form post:

const result = await agent.collect({
  timeoutMs: 3000,
  binding: await getNonceFromMyServer(),  // { nonce, timestamp }, optional
});
await fetch('/api/login', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ email, password, device: result }),
});

The result is plain JSON, about 4 KB. Read Integration for what to check on the server, and Anti-replay binding for the nonce.

6. Tell your users

Device signals can be personal data. Before you deploy, read Privacy and add a notice to your privacy policy.

Try it without building

The live demo at whiskerjs.com/demo runs the real library in your browser and shows every component, both ids and the flags.