Skip to main content
Every visit resolves to six identifiers, and the most durable of them, the DeviceID, holds even after a visitor clears cookies or opens an incognito window. You read the identity and its signals from the webhook or the History API.

The identifier model

Every identify call returns six identifiers. They are ordered here by how durable and useful each one is, from the persistent DeviceID down to the per-call RequestID. RequestID, SessionID, and CookieID are minted in the browser. DeviceID and VisitorID are computed on the server from the collected signals, so the browser never sees them. You correlate everything by RequestID.

Identifier hierarchy

The six identifiers nest from a single request up to a known account:
  • RequestID is one identify call.
  • SessionID is one visit.
  • CookieID is the browser’s first-party storage.
  • VisitorID is the DeviceID and CookieID together, the cookie-scoped identity.
  • DeviceID is the durable, browser-bound device identity.
  • UserHID is the signed-in account you pass in.
A single DeviceID can sit behind many VisitorIDs, many sessions, and many requests over time.

Why DeviceID is durable

DeviceID is the identifier most analytics tools cannot match. The server computes it from hundreds of stable browser and device characteristics. The same browser environment always produces the same DeviceID. Because nothing about it lives in the cookie, it holds when cookie-based tracking breaks:
  • Survives cleared cookies. Clearing cookies removes the CookieID, not the identity.
  • Survives incognito. A private window keeps the same environment, so the DeviceID is stable.
  • Survives IP rotation. Switching networks or using a VPN does not change the identity.
This durability is why a returning person keeps the same DeviceID, even after their cookies expire. It is also the foundation of identification accuracy, where corroborating several independent signals takes anonymity detection up to 99%.
DeviceID is browser-bound. The same person on Chrome and on Firefox produces two different DeviceIDs.
When the snippet is blocked or JavaScript is disabled, no stable characteristics reach the server, so the DeviceID comes back as the all-zero UUID 00000000-0000-0000-0000-000000000000. A JavaScript-disabled visit scores 90. Route a null or all-zero DeviceID to review rather than auto-allowing it: you cannot recognize a returning person from an identity that was never built.

Why VisitorID resets

VisitorID is built from two inputs: the DeviceID and the CookieID. The DeviceID half is durable. The CookieID half is not. So when a visitor clears cookies:
  1. The CookieID is gone, and the browser mints a fresh one on the next visit.
  2. The server combines the same DeviceID with the new CookieID.
  3. The result is a new VisitorID.
That is by design. One durable DeviceID can sit behind many VisitorIDs over time, and the VisitorID only ever moves forward: each cleared-cookie mints a fresh CookieID, so once a device leaves a VisitorID behind, that value does not reappear on it. So if a VisitorID a device already moved past shows up on that same device again (you saw A, then B, then A once more), that is physically impossible under normal use, and a strong sign the cookie was copied or stolen and replayed. This is a basic, built-in check for stolen or copied cookies. Use DeviceID for the most stable handle on a returning person within a browser. Use VisitorID for the cookie-scoped view, and UserHID once a person signs in.
A burst of new VisitorIDs all mapping to one DeviceID, or one VisitorID seen across many DeviceIDs, is itself a signal. The dashboard surfaces these as Patterns.

UserHID is your hashed account id

UserHID is the only identifier you control. It is your own account id, passed into the snippet so ShieldLabs can tie anonymous activity to a known account. Pass a hashed or pseudonymous value, and apply the same transform every time so the same account always maps to the same UserHID.
Never pass a raw email, username, or primary-key user id as the UserHID. ShieldLabs echoes the UserHID back in webhooks and History, so a raw value would put plaintext account data in those payloads. Always hash it or use a pseudonymous token.
When no one is signed in, call checkAnonymous() and the UserHID is left unset. The snippet setup documents the full method list.

Device Intelligence is part of identification

The output of identification is not just an ID. It is the identity plus the signals around that device, delivered together in one response. You never call a separate “fingerprint” endpoint and a separate “risk” endpoint. One snippet collects the signals, the server scores them, and the result arrives by webhook (or you read it from the History API). Browser fingerprinting is one component of Device Intelligence, not the whole thing.

Example response

A realistic webhook body. The six identifiers arrive alongside the Risk Score and the signals that explain it.
Here the score is 30 because three independent network signals each added 10: the IP looks like a proxy, it resolves to a datacenter, and it carries a known-abuser reputation. The signal strings are display labels and can change — never branch on them. Use detection_flags to see which signals fired; the same total score can mean different things depending on which flags are set. Read the Risk Score band, the flags, and the action context together — see Acting on the Risk Score. device_id and visitor_id are the server-derived identity. user_hid is your hashed account id, echoed back. The API models reference documents every field and its types.

Next steps

Anonymity Signals

VPN, proxy, Tor, Privacy Relay, and the mismatch signals around each device.

Risk Scoring

The explainable 0 to 100 score and its bands: Clean, Low, Medium, High.

Accuracy

How corroborating independent signals takes identification up to 99%, and where it stops.