The background-collection pattern
getFingerprint blocks the caller for up to 1–1.6 seconds. For interactive pages that pattern adds measurable latency. The solution is to decouple the start of collection from the moment you need the result.
createCollector returns a CollectorHandle immediately — no collection begins yet. Call start() as early as possible in the page lifecycle (top of a script, inside a DOMContentLoaded handler, or in a framework's app initialiser). Collection then runs in the background. By the time the user has filled a form or clicked a button, getResult() typically resolves instantly because collection finished during idle time.
CollectorHandle methods
start() is idempotent — calling it multiple times is safe; only the first call begins collection. It never throws.
getResult() returns the stored FingerprintResult promise. If start() was never called, getResult() auto-starts collection and waits for it. getResult() also never throws — on any error it resolves to an empty FingerprintResult.
import { createCollector } from 'doorman-benny';
// Place at the very top of your page-load handler.
// Collection begins immediately and runs in the background.
const collector = createCollector();
collector.start();
// ... modules load, network requests fire, user sees the first screen ...
// By now collection is likely done. getResult() resolves with little or no wait.
async function onFormSubmit() {
const result = await collector.getResult();
if (result.automation.automationLikelihood === 'high') {
throw new Error('Automated submission blocked');
}
await submitToServer({
deviceId: result.hardwareFingerprint,
fingerprint: result.fingerprint,
});
}The collector passes the same FingerprintOptions to getFingerprint internally. All options — tiers, timeout, exclude, debug — apply.
Comparison with getFingerprint
createCollector is a scheduling wrapper around getFingerprint. The FingerprintResult it produces is identical in shape. The only difference is when collection starts: immediately with getFingerprint, or at the explicit start() call with createCollector. Use createCollector whenever the page lifecycle gives you any time before you need the result.

