User id · device recognition · agent verification · edge-native

See in
the dark.

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.

< 40 msat the edge
~8 kbgzipped script
incognito-proofno client storage
human / agentbot scoring

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.

collect.darkid.io● resolving
visitorId 4a91e001-069c-4b80 confidence 1.0 kind human user: { userId: u_7f3a…, confidence: 0.82, basis: network }
How it works
A device returns. We recognize it — even with cookies cleared.

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.

01 · Client

Collect

A small (~8 kb gzipped) script reads a vector of device traits — rendering, hardware, locale. No permissions, no intrusive sensors.

02 · Edge

Enrich

A Worker validates your key, adds network signals (ASN, geo) and derives a low-entropy bucket to search.

03 · Match

Resolve

A per-bucket Durable Object runs an exact-then-fuzzy match — serialized, so two requests never split one device.

04 · Decide

Return

You get a stable visitorId + confidence in tens of milliseconds. Recognized or new, ready to gate.

darkid user id
Know the person — not just the device.

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.

device

A single recognised device is returned as the user anchor. Confidence reflects fingerprint match quality — typically high when rendering and hardware signals align precisely.

network

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.

response — user object
// 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.

The signal portfolio
No single trait is decisive.

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.

Rendering

Canvas, WebGL renderer + extended parameter hash, audio stack — how this exact machine paints pixels and shapes sound.

Hardware

Screen geometry, pixel ratio, CPU cores, device memory, plugin count — the physical envelope.

Locale & Math

Timezone, language, platform — plus a hashed Intl/math profile that varies subtly between JS engines and OS locales.

Media environment

A hashed fingerprint of the device's media-query responses — screen gamut, colour scheme, pointer resolution.

Network

ASN and coarse geography from the edge — candidate generation, never identity alone.

Continuity & Contradiction

Recency-weighted recurrence — how recently a fingerprint recurs — and impossible combinations (distant places in seconds, sudden automation) count against a match.

User id & cross-device

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.

Hardware-bound session

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.

Agent intelligence
Human, or agent?

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.

Human  ·  score 0.03 Agent  ·  score 0.91
What darkid looks for

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.

Good bots from bad — verified, not assumed.

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.

✓ signed agent · verified AI crawler · declared spoofed Googlebot · unverified

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.

Real-time risk decisions
A decision, not just a score.

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.

allow challenge step_up block
response — risk object
// 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

Continuous authentication
Still you?

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.

  • Behavioural baseline built silently from mouse movement and typing rhythm as the visitor interacts normally.
  • Consistency score 0–1 returned on every subsequent collect call, feeding directly into the risk engine.
  • Session-takeover signal — a sudden style change flags account sharing or credential-stuffing replay mid-session.

Timing and motion only. No keystrokes, no text, ever.

session integrity 92%
consistent with baseline
session integrity 38%
deviation detected
Built for defenders
Recognition, not surveillance.

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.

  • IPs are HMAC'd, never stored raw; signal components are hashed at the edge.
  • No high-intrusion sensors — no battery, motion, Bluetooth, nearby-Wi-Fi or advertising IDs.
  • Consent & retention are first-class — legal-basis and retention travel with every record.
  • Per-tenant isolation — your devices live in your namespace, reachable only with your key.
embed — one tag, zero config
<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: []
  }
}
See it recognize your device.

Open the demo, then reload — or open it in an incognito window. The identifier won't change.