API Reference

compareFingerprints

Compare two FingerprintResult objects with mode-aware fuzzy matching. Returns a numeric score, a boolean match verdict, and a 15-element diff vector ready for ML consumption.

Signature
compareFingerprints(a: FingerprintResult, b: FingerprintResult, options?: ComparisonOptions): ComparisonResult

Returns: A ComparisonResult containing matchScore (0–100), a match boolean, hardwareMatch, weighted similarity scores, constraint violations, per-signal detail, and a diff vector.

Overview

compareFingerprints compares two FingerprintResult objects collected at different times or in different browser sessions. It applies hard constraint checking first, then per-signal fuzzy matching for signals that have dedicated fuzzy functions, then weighted similarity scoring to produce the final result.

The function never throws. On any uncaught error it returns a safe zero-score default with an empty signalComparison and a 15-element zero diffVector.

Comparison modes

ModeSignal setFuzzy matchingBest for
exactAll signals from both fingerprintsEnabled (unless overridden)Default — all signals with graceful fuzzy tolerance
cross-browserHardware signals only (fonts, webgl_gpu_identity, platform, timezone, media_devices)EnabledMatching the same device across different browser engines
hardware-onlyHardware signals onlyEnabledExplicit hardware-only filter — same signal set as cross-browser, different semantic intent
engine-onlyEngine signals onlyEnabledDetecting browser changes on the same device
strictAll signalsDisabled — hash equality onlyZero tolerance for any signal variation
lenientAll signalsEnabledMaximum tolerance for expected drift

Hard constraint checking

Before any signal scoring, compareFingerprints checks hard constraints. Currently one constraint is active: os_changed, which fires when the normalised platform value (the OS/platform string) differs between the two fingerprints. If checkConstraints is true (the default) and a violation is found, the function returns immediately with matchScore: 0 and match: false.

Even on an early return, hardwareMatch is still computed via string equality of the two hardwareFingerprint fields.

ComparisonOptions fields

FieldTypeDefaultDescription
modeComparisonMode'exact'Signal set and matching strategy preset. See modes table above.
includeSignalsstring[]Further narrows the mode's signal set to only these names.
excludeSignalsstring[]Removes these signal names from the comparison set.
fuzzyMatchingbooleantrueEnable per-signal fuzzy functions for signals that have them.
matchThresholdnumber85Minimum matchScore (0–100) for match: true.
checkConstraintsbooleantrueRun hard constraint checks before comparison.
fuzzyThresholdsFuzzyThresholdsOverride per-signal fuzzy thresholds for audio and screen signals.

Per-signal fuzzy matching

Five signals have dedicated fuzzy functions that score partial matches rather than treating any hash mismatch as zero. For all other signals, a hash mismatch scores 0.0 — there is no fuzzy path. When mode is strict or fuzzyMatching is false, the fuzzy dispatch is bypassed entirely and every signal is scored as 1.0 (match) or 0.0 (mismatch).

Signals with fuzzy functions

SignalWhat is comparedKey tolerance
screenWidth, height, colorDepth, DPR as a 4-element arrayUp to 10% dimension drift scores 0.6; DPR zoom tolerance of 0.5
platformOS string, hwConcurrency, deviceMemory, maxTouchPointsOS must match exactly; each hardware spec adds 0.25 to the score
timezoneTimezone name string and UTC offsetBoth must match exactly — returns 1.0 or 0.0
media_devicesaudioInputCount and videoInputCount (audioOutputCount excluded — Safari privacy)Partial count match scores 0.5
audioArray of DSP samples compared per-element by percentage differenceSamples within 1% score 0.95; within 5% score 0.5

ComparisonResult fields

FieldTypeDescription
matchScorenumberInteger 0–100. Computed as Math.round(similarity * 100).
matchbooleantrue when matchScore >= matchThreshold (default 85).
hardwareMatchbooleanString equality of a.hardwareFingerprint and b.hardwareFingerprint. Always computed, even on early constraint return.
similaritynumberWeighted similarity 0.0–1.0. Hardware signals receive weight 2; engine signals weight 1. Absent signals are excluded.
hardwareSimilaritynumberUnweighted average of hardware-signal matchScores. 0.0–1.0.
constraintViolationsstring[]Array of violation strings, e.g. 'os_changed'. Empty when no violations found.
signalComparisonRecord<string, SignalComparisonDetail>Per-signal breakdown including matchScore and changeType (identical / implausible / plausible / one_absent).
diffVectornumber[]Fixed 15-element float array (0.0–1.0) in SIGNAL_ORDER. Suitable for ML feature input. Signals not in the comparison set are 0.0.
typescript
import { getFingerprint, compareFingerprints } from 'doorman-benny';

const fpA = await getFingerprint();
// ... save fpA, restore later, or collect fpB on a different browser ...
const fpB = await getFingerprint();

// Default comparison — all signals, fuzzy matching, threshold 85.
const result = compareFingerprints(fpA, fpB);
console.log(result.matchScore);       // 0–100
console.log(result.match);            // true if matchScore >= 85
console.log(result.hardwareMatch);    // independent string-equality check
console.log(result.similarity);       // 0.0–1.0 weighted score
console.log(result.diffVector);       // 15-element ML feature vector

// Cross-browser device matching — hardware signals only.
const crossResult = compareFingerprints(fpA, fpB, { mode: 'cross-browser' });
if (!crossResult.match) {
  requireAdditionalVerification('Different device detected');
}

// Strict mode — any signal change fails the match.
const strictResult = compareFingerprints(fpA, fpB, { mode: 'strict' });

// Custom threshold and excluded signals.
const customResult = compareFingerprints(fpA, fpB, {
  matchThreshold: 90,
  excludeSignals: ['speech_voices', 'storage_quota'],
});

compareFingerprints is synchronous — both inputs must already be collected FingerprintResult objects.