Installation
Install the package from npm. The bundle is ~39 KB minified with no runtime dependencies.
npm install doorman-bennyTwo entry points
The library exports two primary functions. Pick one based on what you need to identify.
getDeviceId collects only hardware-bound signals, finishing in roughly 200–300 ms and producing a hash that is stable across Chrome, Safari, Firefox, and Brave on the same machine. getFingerprint runs the full 15-signal pipeline (~1–1.5 s) and returns both a per-browser fingerprint and the same cross-browser hardware hash.
import { getDeviceId, getFingerprint } from 'doorman-benny';
// Cross-browser DEVICE identity — same hash across Chrome, Safari, Firefox, Brave.
const { id, confidence } = await getDeviceId();
console.log(id); // "7c2e9a4b8f1d6e3a"
console.log(confidence); // 0.0–1.0
// Full BROWSER-INSTANCE fingerprint — differentiates same-device sessions.
const result = await getFingerprint();
console.log(result.fingerprint); // per-browser hash
console.log(result.hardwareFingerprint); // cross-browser device hash
console.log(result.consistency); // anti-detect browser detection
console.log(result.incognito); // private-mode detection
console.log(result.automation); // Puppeteer / Playwright / Selenium detectionBoth functions return a Promise and never throw — they return an empty result on any uncaught error.
Background collection
For best perceived performance, start collection early in the page-load cycle using createCollector. Call start() as soon as your script executes, then await getResult() only when you actually need the data. This lets signal collection overlap with network requests and UI rendering.
The collector is idempotent — calling start() more than once is safe, only the first call begins collection. Calling getResult() without ever calling start() auto-starts collection on demand.
import { createCollector } from 'doorman-benny';
// Place this at the top of your page-load handler.
const collector = createCollector();
collector.start(); // begins collecting in the background
// ... user interaction, lazy-loaded modules, network requests ...
// Await the result only when you need it — collection has been running in parallel.
const result = await collector.getResult();
console.log(result.fingerprint);
console.log(result.hardwareFingerprint);createCollector never throws. If something goes catastrophically wrong, getResult() returns an empty FingerprintResult.
Where to go next
Read Configuration to learn the four FingerprintOptions fields — tiers, timeout, exclude, and debug — and when to use each. Browse the API Reference for the full signature of each public function.

