Most of your traffic has no name — no login, no cookie. darkid resolves the person behind it into a stable, confidence-scored user id — nothing on screen. It recognizes the device, tells humans from agents (and verifies the good bots), and links the same person across devices — all passively, server-side.
Fully passive. No prompts, no cookies, nothing written to the device — the user id is speculated server-side, confidence-scored, and never claims certainty without a deterministic anchor.
darkid never trusts what the browser stores. It reads the device's own characteristics, matches them at the global edge, and returns the same identifier next time.
A small (~8 kb gzipped) script reads a vector of device traits — rendering, hardware, locale. No permissions, no intrusive sensors.
A Worker validates your key, adds network signals (ASN, geo) and derives a low-entropy bucket to search.
A per-bucket Durable Object runs an exact-then-fuzzy match — serialized, so two requests never split one device.
You get a stable visitorId + confidence in tens of milliseconds. Recognized or new, ready to gate.
darkid mints an opaque userId and links a person's devices into it — no login, no sign-up, nothing on screen. It's always passive and speculative-with-confidence: certainty is only claimed when a deterministic anchor exists.
A hashed account hint (data-account="sha256(userId)") is shared across devices. When two devices carry the same hash, the link is deterministic — confidence 1.0, no guesswork.
A single recognised device is returned as the user anchor. Confidence reflects fingerprint match quality — typically high when rendering and hardware signals align precisely.
Repeated shared-network co-occurrence probabilistically links sessions across devices. Confidence reflects how often the pattern recurs — never claimed with certainty without a deterministic anchor.
// returned alongside visitorId on every collect call user: { userId: "u_7f3a…", userConfidence: 0.82, basis: "network" }
userId is opaque and stable across sessions. basis tells you how the link was established. userConfidence lets you decide how much weight to give it — use it like a risk signal, not a fact.
Drift and privacy defenses see to that. darkid weighs a spread of evidence and decays it over time — rendering and hardware carry the weight, locale and network narrow the field.
Canvas, WebGL renderer + extended parameter hash, audio stack — how this exact machine paints pixels and shapes sound.
Screen geometry, pixel ratio, CPU cores, device memory, plugin count — the physical envelope.
Timezone, language, platform — plus a hashed Intl/math profile that varies subtly between JS engines and OS locales.
A hashed fingerprint of the device's media-query responses — screen gamut, colour scheme, pointer resolution.
ASN and coarse geography from the edge — candidate generation, never identity alone.
Recency-weighted recurrence — how recently a fingerprint recurs — and impossible combinations (distant places in seconds, sudden automation) count against a match.
darkid mints a stable userId and links devices into it — deterministically via a hashed account hint, or probabilistically from device continuity and shared-network co-occurrence.
On Chrome for Windows and macOS, darkid silently binds the session to a non-exportable key in the device's secure hardware — TPM or Secure Enclave — re-signed in the background, no prompt. A stolen cookie alone can't replay it. Other browsers fall back to passive recognition.
Everything is hashed. No raw personal data is stored. · Hardware-bound sessions (Chrome · Windows & macOS) · UA client hints · installed voices · codec support · CSS feature profile.
Now including WebGPU adapter, font metrics, Intl data, and an edge-read TLS transport fingerprint the page can't spoof.
Resilient by design: a device stays recognized across browser and OS updates via its stable hardware/GPU/network core, and privacy-hardened browsers (Brave, Firefox RFP) are detected and handled instead of fragmenting into new identities.
Automated traffic has tells — and darkid scores them. Every response now includes a kind field and a botScore (0 → 1), computed server-side from a battery of automation evidence.
The scoring layer checks navigator.webdriver, software-rendered GPU signatures, missing browser internals that real browsers always expose, control-protocol artifacts (CDP leak patterns), headless user-agent strings, and plugin / extension absence. None of these signals is individually decisive — the botScore is an aggregate, returned alongside the normal visitorId so you can act on both at once.
Not all automation is hostile. darkid sorts agents into categories — search engines, accessibility tools, AI crawlers, user-directed AI agents, scrapers, monitoring — and verifies the good ones. A matching user-agent never counts: verification is reverse-and-forward DNS or a published IP range. Agents that sign their requests with Web Bot Auth (RFC 9421 / Ed25519) are cryptographically proven into a trusted signed agent class.
Set a disposition per category — allow · tag · challenge · block — and pick a posture (balanced, permissive, strict) as a starting point. Verified good bots are welcomed even at higher risk; a spoofed user-agent earns nothing.
Every darkid call returns a machine-readable action — derived from identity, agent detection, and network-velocity evidence — plus the reason codes your code acts on directly. Set your own thresholds and evidence weights per tenant; changes apply at the edge in seconds.
// returned alongside visitorId on every collect call risk: { score: 0.62, action: "step_up", reasons: ["ip_velocity_high", "new_device"] }
Reason codes: automation_detected · ip_velocity_high · request_rate_high · new_device · no_account · low_confidence
darkid learns how each visitor drives the session — pointer dynamics and keystroke timing (never key contents) — and produces an in-session consistency score. A mid-session takeover raises risk even when the device fingerprint is unchanged.
Timing and motion only. No keystrokes, no text, ever.
darkid is a first-party security tool. The data it handles is pseudonymous personal data — and it's treated that way from the first byte.
<script src="https://darkid.io/v0/darkid.js" data-key="pk_live_…" data-account="sha256(userId)"></script> // data-account links the same user across devices. // Pass a hash — never raw PII. // next tick: window.darkid = { visitorId: "4a91e001-069c-…", confidence: 1.0, isNew: false, kind: "human", botScore: 0.03, user: { userId: "u_7f3a…", userConfidence: 0.82, basis: "network" }, risk: { score: 0.07, action: "allow", reasons: [] } }
Open the demo, then reload — or open it in an incognito window. The identifier won't change.