The pipeline
getFingerprint runs four sequential stages. First, runCollectors launches all configured signals in parallel with a global timeout — every signal that completes before the deadline writes its result; any that do not are recorded as absent.
Second, computeCrossBrowserScore derives the hardware hash from the subset of hardware-bound signals. Third, consistency checks, incognito checks, and automation checks run in parallel — none depend on each other. Finally, fuseSignals combines everything into the composite fingerprint hash and packages the FingerprintResult.
On any uncaught error, the function returns an empty FingerprintResult rather than throwing.
Two hashes from one call
The result carries two fingerprints. fingerprint is computed from all 15 signals and differs between Chrome and Safari on the same machine — engine-bound signals like audio DSP and canvas rasterisation diverge across browser engines. hardwareFingerprint is computed only from the five hardware-bound signals and is stable across browsers and incognito on the same physical device.
Both hashes are 16-char hex strings. You only need to call getFingerprint once to get both.
FingerprintResult fields
| Field | Type | Description |
|---|---|---|
| fingerprint | string | 16-char hex. Full hash fused from all collected signals. Differs per browser engine. |
| hardwareFingerprint | string | 16-char hex. Hardware-only hash. Stable across Chrome, Safari, Firefox, Brave on the same device. |
| version | string | Library version string. |
| collectionTimeMs | number | Wall-clock time for the entire collection pass. |
| signals | Record<string, SignalResult> | Per-signal result map — hash, confidence, binding, and (in debug mode) raw value. |
| consistency | ConsistencyResult | Anti-detect browser detection. spoofLikelihood: 'low' | 'medium' | 'high'. |
| incognito | IncognitoResult | Private-mode detection. incognitoLikelihood: 'low' | 'medium' | 'high'. |
| automation | AutomationResult | Automation-framework detection (Puppeteer, Playwright, Selenium). automationLikelihood: 'low' | 'medium' | 'high'. |
| crossBrowser | CrossBrowserScore | Cross-browser confidence score with stableSignals and unstableSignals lists. |
import { getFingerprint } from 'doorman-benny';
const result = await getFingerprint();
// Two hashes from one call.
console.log(result.fingerprint); // per-browser instance
console.log(result.hardwareFingerprint); // cross-browser device hash
// Three independent risk tracks.
if (result.consistency.spoofLikelihood === 'high') {
flagForReview('Anti-detect browser detected');
}
if (result.automation.automationLikelihood === 'high') {
blockRequest('Automation framework detected');
}
// Incognito is informational — private browsing is not evidence of fraud.
console.log(result.incognito.incognitoLikelihood);
// Per-signal detail.
for (const [name, signal] of Object.entries(result.signals)) {
console.log(name, signal.confidence, signal.binding);
}Treat 'medium' as suggestive and 'high' as conclusive for spoofLikelihood and automationLikelihood.

