Browser fingerprinting SDK

Browser fingerprinting SDK docs

Install the browser fingerprinting SDK and visitor ID JavaScript library, send browser signals to POST /api/identify, and fetch authoritative smart signals from your server. Use Events GET for online fraud detection workflows — account takeover prevention, credential stuffing defense, and bot detection API playbooks — with a persistent originId.

Browser

POST /api/identify

Your backend

Store eventId

Events API

GET/PATCH /api/events/:eventId

Your policy

Gate on confidence + account

Use each eventId once within a 5-minute decision window. Fraud fields never belong in the browser.

What this SDK does

The browser fingerprinting SDK and visitor ID JavaScript client collect device signals in-browser, then your backend decides with server-authoritative enrichment.

DigitalFingerprint is a visitor identification platform delivered as a JavaScript SDK. Use it when you need a persistent visitor ID across cleared cookies, VPNs, and many private-browsing scenarios — without trusting fraud fields returned to the browser. Start with install, then wire Events GET before signup, checkout, or other high-value actions.

Quick start

Production integrations follow a three-step trust model. Gate sensitive actions on confidence plus account, not originId alone.

  1. 01

    Install the SDK

    Install @digitalfingerprintjs/client from npm, load cdn.digitalfingerprintjs.com, or import the Google Tag Manager template — then init with your public browser key (pk_…).

  2. 02

    Identify in the browser

    POST browser signals to https://api.digitalfingerprintjs.com/api/identify. Production keys return a slim payload; store eventId on your backend.

  3. 03

    Enrich server-side

    Fetch authoritative smart signals via GET /api/events/:eventId with a secret server key (sk_…). Attach account/order metadata after identify with PATCH /api/events/:eventId (linkedId/tags). Optionally GET /api/drn/:originId for global device reputation. Never trust fraud fields from the client.

Installation

Package @digitalfingerprintjs/client, public SDK class OriginID. The SDK collects 95+ browser signal fields on Chromium.

app.ts

npm install @digitalfingerprintjs/client
// or CDN: https://cdn.digitalfingerprintjs.com/v1/originid.global.js

import { OriginID } from "@digitalfingerprintjs/client";

const oid = OriginID.init({
  endpoint: "https://api.digitalfingerprintjs.com/api/identify",
  apiKey: process.env.NEXT_PUBLIC_ORIGINID_PUBLIC_KEY, // pk_… public browser key
  onIdentify: (result) => {
    // Production: send result.eventId to your backend
    console.log(result.originId, result.eventId);
  },
});

await oid.ready();

Analytics / marketing

Single assignment path with optional confidence gating on sensitive actions via Events GET. Import the analytics-marketing rules preset from the console Limiter.

analytics-init.ts

import { OriginID } from "@digitalfingerprintjs/client";

// Analytics / marketing: import analytics-marketing rules preset from Limiter
const oid = OriginID.init({
  endpoint: "https://api.digitalfingerprintjs.com/api/identify",
  apiKey: process.env.NEXT_PUBLIC_ORIGINID_PUBLIC_KEY, // pk_…
  onIdentify: (result) => {
    // Send result.eventId to your backend for Events GET (secret sk_… key)
    console.log(result.originId, result.eventId);
  },
});

await oid.ready();
// Backend: gate sensitive actions when event.identification.confidence < 90

Fraud / signup pattern

Gate on confidence + rules via Events GET before sensitive actions. SDK auto-seeds clientToken since v1.0.

fraud-init.ts

import { OriginID } from "@digitalfingerprintjs/client";

// Fraud / signup: gate on confidence + rules via Events GET
const oid = OriginID.init({
  endpoint: "https://api.digitalfingerprintjs.com/api/identify",
  apiKey: process.env.NEXT_PUBLIC_ORIGINID_PUBLIC_KEY, // pk_…
  identifyOnDemand: true, // before OTP, checkout, password reset
  getIdentifyMetadata: () => ({ linkedId: currentUserId }),
});

const { eventId } = await oid.ready();
// Backend: GET /api/events/:eventId with sk_… → gate on confidence + linkedId

Script tag

Serve originid.global.js from your origin or a CDN build of @digitalfingerprintjs/client. Prefer Google Tag Manager when you cannot redeploy site code.

index.html

<script
  src="https://cdn.digitalfingerprintjs.com/v1/originid.global.js"
  integrity="sha384-sLnmYFAc9KQJmcBlbZOiHELB9o2AttpyJTvc12Z4yYpGrYGN6roK3o9zso58YPXJ"
  crossorigin="anonymous"
></script>
<script>
  OriginID.init({
    endpoint: "https://api.digitalfingerprintjs.com/api/identify",
    apiKey: "YOUR_PUBLIC_API_KEY", // pk_… never use sk_ in the page
  })
    .ready()
    .then((r) => console.log(r.originId, r.eventId));
</script>

Google Tag Manager

Deploy DigitalFingerprint through GTM without changing website code. Identification results are pushed to the dataLayer for other tags.

Download the tag template, import it under GTM Templates, create a DigitalFingerprint tag with your public key (pk_…), and trigger on Initialization. Allowlist your website hostname on the key.

Template: https://cdn.digitalfingerprintjs.com/integrations/gtm/v1/template.tpl

The template loads the adapter at https://cdn.digitalfingerprintjs.com/integrations/gtm/v1/adapter.iife.min.js (not imported manually).

dataLayer result

After identify, read DigitalFingerprintResult.originId (Data Layer Variable) and fire dependent tags on custom event DigitalFingerprint.identified. Optional first-party proxy: set an endpoints row to your identify URL.

datalayer.js

window.dataLayer.push(function () {
  if (this.get("DigitalFingerprintResult")) {
    const result = this.get("DigitalFingerprintResult");
    console.log(result.originId, result.eventId);
  }
});

Preview checklist

  • DigitalFingerprint tag fires on Initialization (or your chosen trigger)
  • dataLayer shows DigitalFingerprint.started then DigitalFingerprint.identified
  • DigitalFingerprintResult.originId and eventId are present
  • A matching visit appears in the DigitalFingerprint dashboard

SDK configuration

OptionDefaultDescription
endpointhttps://api.digitalfingerprintjs.com/api/identifyProduction identify URL (use relative /api/identify only for same-origin or CDN first-party proxy)
apiKeyn/aPublic browser key (pk_…) → Authorization: Bearer (hostname-bound)
environmentn/aOptional production | staging override when key policy allows
responseModeslim (prod keys)slim | full; appends ?response=full when set to full
signingSecretn/aNot used with public keys (CAD-2). Legacy/self-host only — never put platform ORIGINID_SECRET in SaaS frontend JS
clientToken (auto)SDK defaultAuto-seeded on init when storage empty (cookie + localStorage); pre-seed via inline script for WebView bridges
autoIdentifytrueCall identify automatically on init
identifyOnDemandfalseSkip in-memory cache; full collect + POST on every identify/ready (use before OTP/checkout)
collectDelayMs0Defer heavy async probes until after first paint
disabledProbes[]Probe IDs sent as "disabled" in the payload
getIdentifyMetadatan/aReturns { linkedId?, tags? } merged into each identify body
onIdentifyn/aCallback on successful identify
onErrorn/aCallback on identify failure

Methods

MethodDescription
OriginID.init(config)Create SDK instance; auto-identifies when autoIdentify is true
oid.identify(signals?, metadata?)Collect signals (if omitted) and POST to identify
oid.ready()Promise that resolves after auto-identify completes
oid.getOriginId()Latest originId after identification
oid.getResult()Latest full or slim response object
collectSignals()Low-level: gather browser signals without identifying

linkedId and tags

Attach stable business identifiers on each identify. Limits: linkedId 255 chars; up to 20 tag keys (64 / 256 chars). These are visit metadata, they do not change how originId is assigned.

identify.ts

await oid.identify(undefined, {
  linkedId: "user_12345",
  tags: { plan: "pro", signup_source: "web" },
});

First-party clientToken

The server may return clientToken in slim responses for returning-visitor continuity. The SDK persists it in localStorage (normal browsing) or sessionStorage (incognito). Incognito tokens never write to durable storage and are linked to normal profiles via privacy-profile matching when hardware aligns.

POST /api/identify

Accepts collected browser signals plus optional linkedId, tags, clientToken, and sessionToken.

Request integrity

Public browser keys use platform-managed integrity (hostname allowlisting). Do not put platform ORIGINID_SECRET or a customer signingSecret in frontend JS. Legacy oid_… keys remain dual-accept during migration (self-host may use ORIGINID_REQUEST_SIGNING=required).

Query parameters

ParameterEffect
?response=slimForce slim browser payload (originId, eventId, clientToken, timestamp)
?response=fullReturn full identify JSON (staging/debug; not for production fraud logic)
?format=fingerprintFingerprint-compatible JSON export (requires full response mode)
?ruleset_id=rs_…Optional. Evaluate one ruleset before persist; block responses are unbilled

Slim response (production default)

Production keys default to slim unless overridden by query or per-key policy. Fraud fields such as confidence and smartSignals are never in slim browser payloads.

  • originId
  • eventId
  • clientToken
  • timestamp

Error responses

Rejects include rejectReason and billed: false when no visit is persisted.

HTTPrejectReasonNotes
401invalid_keyMissing or invalid API key
403HOSTNAME_NOT_ALLOWEDBrowser Origin/Referer hostname not on the key allowlist
403invalid_signature / waf_blockBad HMAC signature or edge WAF block (unbilled)
402plan_usage_exceededHosted plan quota exceeded (when BILLING_ENFORCE_USAGE=true)
409invalid_signatureDefinitive signature replay when signing is required
429rate_limitPer-IP (60/min) or per-clientToken (120/min) limit exceeded

Confidence & rules

Single continuity-first assignment path on every API key. Fraud vs analytics posture is confidence v2 + rules presets + Events GET gating, not merge policies.

ConceptDescription
Single assignment pathContinuity-first matching on all API keys: single assignment path for all keys
Explainable matchingmatchPath (stable_hash, rule_matcher, privacy_profile_link, global_fingerprint): explainable continuity — no black-box ML
Confidence v20–100 merge false-positive risk; fusion penalties cap fingerprint merges at 70–89 on shared hardware
Rules presetsImport analytics-marketing, signup-protection, or shared-devices from console Limiter
Events GET gatingGate signup when confidence < 90 and no linkedId (Fingerprint 0.90 equivalent)

Rules preset integration

PresetLabelWhen to use
analytics-marketingAnalytics & marketingLog all visits; optional confidence gating via Events GET
signup-protectionFraud & signupBlock or step-up when confidence < 90 via Events GET + Limiter
shared-devicesCorporate fleets & kiosksExtra guards when identical hardware may share an originId

First-party clientToken

SettingDescription
clientToken auto-seedSDK 1.0+ seeds first-party token on init (normal browsing)
token_matchMatching clientToken → confidence 100, same originId
global_fingerprintCross-org continuity: exact stable+recall or probabilistic ≥90 → same originId; metrics stay per-tenant
IncognitoSession token only; privacy_profile_link for cross-mode continuity (Safari, Chrome, Firefox, Brave, Samsung Internet, iOS Safari)

Import rules presets from the console Limiter or via POST /api/management/v1/api-keys project setup. Fraud vs analytics posture is expressed through rules presets and Events GET confidence gating , not per-key assignment forks.

GET/PATCH /api/events/:eventId

Authoritative enrichment for a single identify event. Confidence and smartSignals are stored at identify time, never recomputed. PATCH updates linkedId/tags after identify.

server.ts

// Your backend: authoritative enrichment (never trust browser fraud fields)
const rulesetId = process.env.ORIGINID_RULESET_ID; // optional, from /dashboard/rules
const apiBase = "https://api.digitalfingerprintjs.com";
const url = rulesetId
  ? `${apiBase}/api/events/${eventId}?ruleset_id=${rulesetId}`
  : `${apiBase}/api/events/${eventId}`;
const res = await fetch(url, {
  headers: { Authorization: `Bearer ${ORIGINID_API_KEY}` }
});
const event = await res.json();
// event.identification.confidence, event.smartSignals, event.ruleAction

Key response fields

  • identification.originId
  • identification.confidence
  • identification.confidenceVersion
  • identification.linkConfidence
  • identification.linkOriginId
  • confidencePenalties
  • smartSignals
  • suspectScore
  • riskLevel
  • riskBreakdown
  • matchPath
  • highRecall
  • deviceReputation
  • browserDetails
  • ipInfo
  • linkedId
  • tags
  • ruleAction
  • rulesetEvaluation

?format=fingerprint returns Fingerprint-compatible JSON (confidence 0–1). Native JSON uses scale 0–100. ?include=raw adds raw signal blobs when PERSIST_RAW_SIGNALS=true. Rate limits: default 600/min per API key, 1000/min per organization. Native Events JSON may include deviceReputation; the Fingerprint Accept export omits it — use GET /api/drn/:originId instead. After identify, PATCH /api/events/:eventId with linkedId / tags (full replace when tags present; secret key only).

Limiter (Beta)

Create rulesets at /dashboard/rules. Enabled rulesets evaluate on every POST /api/identify, the first matching block rule returns an unbilled response. Pass ?ruleset_id=rs_… on Events GET for inline evaluation.

Field / paramDescription
Enabled rulesets (auto)All enabled project rulesets evaluate on POST /api/identify; first block wins (unbilled)
?ruleset_id=rs_… (Events GET)Evaluate one ruleset inline; response includes ruleAction and rulesetEvaluation
?ruleset_id=rs_… (identify)Optional. Evaluate one ruleset before persist instead of all enabled rulesets
ruleActionMatched rule result: allow or block with status, headers, and body
rulesetEvaluationStatus when ruleset_id query param was passed (evaluated or not_found)

GET /api/drn/:originId

Fingerprint-style device reputation across soft-linked clusters. Secret key only. Never returns other tenants' events.

Query by the public originId from identify. When the same device was minted under two IDs (e.g. hardware overlap without strong stable+recall agreement), DRN aggregates suspect scores and timestamps across the cluster. Response fields: canonicalOriginId, clusterOriginIds, suspectScore.minimum/maximum (30-day window), timestamps.

drn.ts

const res = await fetch(
  "https://api.digitalfingerprintjs.com/api/drn/" + encodeURIComponent(originId),
  { headers: { Authorization: "Bearer " + process.env.ORIGINID_SECRET_KEY } },
);
const reputation = await res.json();

Confidence model

identification.confidence expresses merge false-positive risk (0–100), not population uniqueness.

FieldDescription
identification.confidence0–100 merge false-positive risk (not population uniqueness); persisted per visit
identification.confidenceVersion2 (Fingerprint-aligned false-positive merge risk; `2.0` on Fingerprint export)
identification.linkConfidencePrivacy-link score when primary originId differs from link target (e.g. normal ↔ incognito continuity)
confidencePenalties[]tls_binding_mismatch, ip_timezone_history, linked_id_velocity; caps merge confidence to 70–89
highRecallSupplementary originId when recallHash points elsewhere (primary confidence capped at 85 on link paths)

v2 semantics

All new visits use confidenceVersion: 2. Token match and new visitors score 100 (Fingerprint 1.0). Fingerprint merges cap at 99; fusion penalties drop confidence to 70–89.

Signup gate example

Map Fingerprint 0.90 threshold to native 90. Always combine confidence with linkedId for returning accounts.

signup-gate.ts

const event = await fetch(`https://api.digitalfingerprintjs.com/api/events/${eventId}`, {
  headers: { Authorization: `Bearer ${SECRET_KEY}` },
}).then((r) => r.json());

const confidence = event.identification.confidence; // 0–100 native
const linkedId = event.linkedId;

if (confidence < 90 && !linkedId) {
  return blockSignup("step_up_required");
}

Smart Signals

Computed server-side after geo lookup and visit history are known. Never returned in slim browser responses.

FieldDescription
botAutomation detection; includes result (good/bad/unknown) and optional bot_info
vpnVPN detection with confidence and method flags (timezone, relay, etc.)
proxyProxy type (residential, datacenter, tor) and confidence
tamperingBrowser integrity signal
tamperingDetailsanomalyScore, antiDetectBrowser, plugin/WebGL mismatches
incognitoPrivate browsing detected in client signals
privacySettingsPrivacy-hardened browser settings
developerToolsDevTools open at collection time
virtualMachineVM environment heuristic (≥2 indicators)
locationSpoofingImpossible travel, language-region mismatch, or mobile GPS vs IP
mitmAttackTLS/UA interception: v1 heuristic or v2 TLS-corroborated (pro/enterprise)
mitmTlsCorroboratedTrue when mitmAttack used v2 edge TLS corroboration
velocityRolling 5m / 1h / 24h windows for IPs, countries, events, linkedId fanout
ipInfoGeo, ASN, ISP, datacenter flags for IPv4/IPv6
ipBlocklistTor, attack-source heuristics, email-spam lists
highActivityDevicePercentile or absolute high-activity rules per project
mobileRoot/jailbreak/emulator/integrity fields (native SDKs; defaults on web)
sdkplatform and version of the collecting SDK

Suspect score and risk level live on the event root (suspectScore, riskLevel, riskBreakdown) with breakdown dimensions: network, reputation, integrity, automation, identity, environment, trust.

bot_info: Web Bot Auth

Events API includes smartSignals.bot.info with Web Bot Auth (RFC 9421) verification. Verified agents upgrade to result: good; spoofed crypto failures force bad.

FieldDescription
resultgood | bad | unknown | not_detected; verdict after server corroboration + Web Bot Auth
identitysigned | verified | unknown | spoofed; prefer over legacy bot field (Fingerprint v4)
categoryai_agent | ai_assistant | ai_browser | browser_automation | …
providerOperator vendor, e.g. OpenAI, Google
nameHuman-readable agent name, e.g. ChatGPT-User
typeLegacy compat; use category when present
verifiedLegacy compat; true when identity is signed or verified
spoofedLegacy compat; true when identity is spoofed

Edge Automation Intelligence (no-JS)

On pro / enterprise plans, forward edge classification headers on identify when the JS agent is not used. OriginID persists the result in smartSignals.bot.info (same as Events GET and webhooks).

HeaderDescription
x-df-bot-categoryAgent category (pro/enterprise only); alias x-fingerprint-bot-category
x-df-bot-providerOperator vendor
x-df-bot-nameAgent display name
x-df-bot-identitysigned | verified | unknown | spoofed

High-activity device

Rolling 7d event counts per project in Valkey flag the top 0.2% of visitors (default 99.8 percentile) once a project has ≥1000 visitors. Override per API key via policy.highActivityPercentile. Nightly job: GET /api/cron/high-activity-percentile with CRON_SECRET.

Full Smart Signals reference ↑

Limiter presets

Starting-point rulesets for console import, Developer → Limiter → Import preset.

Preset slugUse case
signup-protectionRegistration and checkout: blocks bots, tampering, and risky signups
analytics-marketingAnalytics and marketing: light protection, low friction
shared-devicesKiosks and corporate fleets: extra guards for reused hardware

Account takeover & fraud playbooks

Account takeover prevention, credential stuffing detection, visitor ban enforcement, and bot detection API patterns — decide on your server after Events GET.

Install the SDK, call identify, send eventId to your backend, then GET /api/events/:eventId with a secret sk_… key before you allow, challenge, or block. Never trust browser slim fields for fraud decisions. Example thresholds below are illustrative only — tune them in your policy; they are not product defaults. Optional: apply the same rules to webhook identify.succeeded payloads.

PlaybookTriggerExample policy (tunable)
Account takeover preventionLogin successBlock bad bots; step-up MFA on new originId + confidence < 90; challenge linkedId visitor velocity
Credential stuffing detectionLogin attempt (incl. failures)Block bad bots; friction on high suspectScore; rate-limit velocity bursts; optional proxy/VPN friction
Visitor ban enforcementIdentify / sensitive actionPersist banned originId in your DB; deny when Events GET originId matches

Account takeover prevention

Stop account takeover after login succeeds: fetch Events GET, block bad bots, step up MFA when a new originId arrives with low confidence, and challenge linkedId visitor velocity before issuing a full session.

Full tutorial →

Credential stuffing detection

Defend every login attempt — including failures — with bot detection API signals, high suspectScore friction, and velocity rate limits. Never trust a client originId alone for online fraud detection.

Full tutorial →

Visitor ban enforcement

Enforce visitor bans with fraud detection fingerprinting: resolve originId from Events GET, look it up in your customer-owned ban store, and deny sensitive actions. Bans are browser-scoped.

Full tutorial →

VPN and proxy friction examples remain optional while hosted IP intelligence runs in vendor mode (fixture-backed until live minFraud credentials).

Webhooks

Async delivery after each successful identify, full Events JSON, not slim SDK shape.

Register HTTPS endpoints in the dashboard (Developer → Webhooks). Envelope type identify.succeeded with data matching Events GET. Delivery is at-least-once with up to 5 retries; dedupe on webhook id within 72 hours.

Verify X-OriginID-Signature

  1. Read raw POST body bytes before JSON parsing.
  2. Parse t and v1 from X-OriginID-Signature (format: t={unix},v1={hex_hmac_sha256}).
  3. Reject if |now - t| > 300 seconds.
  4. Compute HMAC-SHA256 over {t}.{rawBody} using your endpoint signing secret.
  5. Compare v1 to the hex digest using constant-time comparison.

webhook-handler.ts

// Verify X-OriginID-Signature on incoming webhook POST
const rawBody = await request.text();
const header = request.headers.get("X-OriginID-Signature") ?? "";
const t = header.match(/t=(\d+)/)?.[1];
const v1 = header.match(/v1=([a-f0-9]+)/)?.[1];
if (!t || !v1 || Math.abs(Date.now() / 1000 - Number(t)) > 300) {
  return new Response("stale", { status: 401 });
}
const expected = hmacSha256Hex(signingSecret, `${t}.${rawBody}`);
if (!timingSafeEqual(v1, expected)) {
  return new Response("invalid", { status: 401 });
}

Fingerprint migration

Industry-shaped JSON export and threshold migration notes for teams moving adapters.

Confidence threshold mapping

Fingerprint (0–1)OriginID native (0–100)
1.0100
0.9595
0.9090
0.7070

Use ?format=fingerprint on identify and Events GET for adapter-compatible JSON. Map visitor_id → originId; confidence is 0–100 in native JSON and 0–1 in Fingerprint export.

fingerprint-export.ts

// Migration: Fingerprint-compatible JSON on Events GET
const res = await fetch(
  `https://api.digitalfingerprintjs.com/api/events/${eventId}?format=fingerprint`,
  { headers: { Authorization: `Bearer ${SECRET_KEY}` } }
);
const fp = await res.json();
// fp.visitor_id → originId; fp.confidence.score is 0–1

Go live

DigitalFingerprint hosts identify, enrichment, and the console, point your SDK and backend at the production API.

Production endpoints

SurfaceURLPurpose
Consolehttps://dashboard.digitalfingerprintjs.comAPI keys, allowed hostnames, Limiter, webhooks, visitor timeline
Identifyhttps://api.digitalfingerprintjs.com/api/identifyBrowser POST: signal collection, match, and enrich
Eventshttps://api.digitalfingerprintjs.com/api/events/:eventIdServer GET: smart signals, suspect score, confidence, ruleAction, deviceReputation
Device reputation (DRN)https://api.digitalfingerprintjs.com/api/drn/:originIdServer GET: cluster-level suspect score rollup + timestamps (secret key)
Account linkhttps://api.digitalfingerprintjs.com/api/account-linkServer POST: duplicate registration scoring at signup

Browser traffic posts to https://api.digitalfingerprintjs.com/api/identify. Your backend fetches enrichment from https://api.digitalfingerprintjs.com/api/events/:eventId with the same secret API key. Do not POST identify to the marketing apex; digitalfingerprintjs.com/api/* is GET-only.

Secrets and configuration

ItemWhere to get it
Public API keypk_… from console → browser OriginID.init apiKey (hostname-bound)
Secret API keysk_… from console → server Authorization: Bearer on Events GET only
Ruleset IDOptional public ruleset id from Limiter → ?ruleset_id on Events GET
Webhook secretPer-endpoint signing secret from Developer → Webhooks

Production checklist

Complete before production cutover.

  • Public browser key (pk_…) on identify; secret server key (sk_…) on Events GET
  • Browser SDK endpoint: https://api.digitalfingerprintjs.com/api/identify (not marketing apex; apex /api/* is GET 301 only)
  • Install via npm @digitalfingerprintjs/client or official CDN cdn.digitalfingerprintjs.com
  • Before production traffic (optional): Settings → Subdomains for first-party identify proxy; allowlist site hostname (SITE_ORIGIN)
  • Allowed hostnames configured on each public API key (site host required when using a first-party proxy)
  • No platform ORIGINID_SECRET / signingSecret in frontend JS (public keys use platform-managed integrity)
  • Slim response verified; no smartSignals in browser payloads
  • Backend tested: identify → eventId → GET /api/events/:eventId (and PATCH linkedId/tags when needed) with secret key
  • Optional: GET /api/drn/:originId for global device reputation (secret key)
  • Confidence thresholds migrated (Fingerprint 0–1 → OriginID 0–100)
  • Sensitive actions use identifyOnDemand: true + Events GET (not cached browser identify)
  • Production security review checklist completed

Changelog

  • NewGoogle Tag Manager

    Import DigitalFingerprint template.tpl into GTM — Start and identify without redeploying your site. Results push to dataLayer as DigitalFingerprintResult (do not send originId to Google Analytics).

  • NewGlobal device reputation (DRN)

    GET /api/drn/:originId and Events deviceReputation — Fingerprint-style cluster rollups across orgs while metrics stay per-tenant.

  • NewWeb Bot Auth verification

    bot_info.verified and bot_info.spoofed on Events GET with RFC 9421 Ed25519 signature validation for AI agents and search bots.

  • NewHosted identify platform

    Fully managed identify, Events API, and console at api.digitalfingerprintjs.com with no infrastructure to deploy on your side.

  • UpdateConfidence v2

    Confidence v2 on all new visits: merge false-positive risk scale, linkConfidence, fusion penalties, high-activity cap.

  • BreakingSDK 1.0: default clientToken seeding

    SDK auto-seeds first-party clientToken on init (Fingerprint parity). bootstrapToken config removed.

  • UpdateLimiter on identify

    Enabled rulesets auto-enforce on POST /api/identify; Events GET supports inline ?ruleset_id evaluation.

  • UpdateRules presets

    Importable Analytics & marketing, Signup & fraud protection, and Shared & corporate devices ruleset templates.

  • UpdateProduction trust model

    Production API keys default to slim browser responses; fraud fields via Events GET or webhooks.

  • InfoDigitalFingerprint branding

    Public product name DigitalFingerprint; SDK class OriginID (@digitalfingerprintjs/client); visitor identifier originId.

Ready to integrate?

Create a project in the console, copy your API key, and follow the quick start guide above.