> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shieldlabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Privacy & data handling

> Learn what ShieldLabs collects, how it is handled, and the controls you have over the data.

ShieldLabs identifies visitors as **entities, not named individuals**. The snippet collects technical attributes of the browser, device, and network connection and posts them to the server, which derives the identifiers (VisitorID, DeviceID) and a [Risk Score](/features/risk-scoring) and delivers those to your backend. It never asks for, sees, or stores who the person actually is.

This page describes what is and is not collected and how you stay in control of the data. Transport, key, and webhook-verification practices live on the [Security](/security) page.

<Note>
  This page describes data handling factually. It is not legal advice and makes no regulatory compliance claim. How you disclose ShieldLabs in your own privacy policy, and on what legal basis you process this data, is your decision to make with your own counsel. For the formal document, see the [Privacy Policy](/legal/privacy-policy), the [Terms of Service](/legal/terms), and the [Cookie & Tracking Policy](/legal/cookie-policy).
</Note>

## What ShieldLabs collects

The snippet reads technical signals from the browser environment and the network connection. These are the raw inputs the server turns into identifiers and the Risk Score.

| Category                | Examples                                                                                                                                   | Used for                                                                 |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
| **Browser fingerprint** | Hundreds of stable browser and device characteristics                                                                                      | Deriving the durable DeviceID                                            |
| **Device and OS**       | Browser name, operating system, device type, timezone                                                                                      | Identification and mismatch checks                                       |
| **Network**             | IP address (read server-side from the connection), connection type, VPN/proxy/Tor/datacenter indicators, network and connection indicators | [Anonymity detection](/features/anonymity-signals) and anonymity signals |
| **Page context**        | The current page URL (with the `#fragment` stripped) and the referrer                                                                      | [Traffic source](/features/traffic-analytics) attribution                |
| **Client-side ids**     | A first-party `cookieID` and a `sessionID`, both minted by the snippet                                                                     | Linking calls from the same browser and visit                            |

The full inventory is roughly 100+ browser, device, and network signals, detailed in the [scoring reference](/features/anonymity-signals) and the end-to-end [How it works](/overview) flow.

## What ShieldLabs does NOT collect

ShieldLabs has no field for, and never asks for, any of the following:

* **Names, emails, or phone numbers.**
* **Passwords.** No site-user credentials are read or stored.
* **Payment data.** No card numbers, no bank details.
* **Form field contents.** The snippet does not read what a visitor types.
* **Full browsing history.** Only the current page URL and the referrer are captured, for traffic attribution.

A ShieldLabs identity answers "is this the same browser/device as before, and how anonymous is this connection?" It does not answer "who is this person?" Visitors are entities described by a VisitorID and a DeviceID, not named accounts.

## UserHID: you supply it, and it must be pseudonymous

`UserHID` is the one field that comes from you, not from the browser. It is your own account id, passed into the snippet so ShieldLabs can correlate a logged-in user's activity across visits and devices.

<Warning>
  **Always pass a hashed or pseudonymous value. Never pass a raw email, username, or account id.** ShieldLabs does not need to know who your user is, only that two requests belong to the same internal account. A one-way hash gives you that link without ever sending us a real identifier.
</Warning>

<CodeGroup>
  ```js Native JS theme={null}
  // Hash your internal user id before passing it in.
  const enc = new TextEncoder().encode(currentUser.id);
  const digest = await crypto.subtle.digest("SHA-256", enc);
  const hashedId = [...new Uint8Array(digest)]
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");

  const mod = await import(
    "https://cdn.shieldlabs.ai/snippet.js?publicKey=YOUR_PUBLIC_KEY"
  );
  mod.checkAuthenticatedUser(hashedId);
  ```

  ```js Wrong theme={null}
  // Do NOT do this. Never pass raw PII as the UserHID.
  mod.checkAuthenticatedUser(currentUser.email); // raw email
  mod.checkAuthenticatedUser(currentUser.id);    // raw account id
  ```
</CodeGroup>

The same hashing applies to `forceCheckAuthenticatedUser`. When you call `checkAnonymous`, no user id is sent at all (the `UserHID` defaults to `anonymous`), as the full client API in the [snippet reference](/setup/snippet) lays out.

## Two network addresses, kept distinct

ShieldLabs works with two different network addresses, and they are never mixed.

* The connection's **public `IP`** is read server-side from the request and used to derive location, reputation, and the [anonymity detection](/features/anonymity-signals) signals that flag a masked connection.
* The **local IP** is the device's own private network address, observed during identification. It feeds a server-side correlation field that lets you tell whether two requests came from the same local network, alongside the other additional network-intelligence fields in the [History API](/api/server-api) snapshot and on the dashboard.

Keep the local IP correlation field server-side. It exists for matching requests to each other, not for display, so do not surface it to your own users.

## Client-side storage

To recognize a returning browser without a server round trip, the snippet keeps two values in the visitor's own browser:

| Value       | Where it lives                                                              | Lifetime                                                      |
| ----------- | --------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `cookieID`  | A first-party cookie and `localStorage` (`SameSite=Lax`, `Secure` on HTTPS) | 2 years, lost when the visitor clears cookies or site storage |
| `sessionID` | `sessionStorage`                                                            | The current visit (a short-lived window)                      |

Both are random UUIDs minted on the visitor's device. They are first-party only. The durable **DeviceID is derived server-side from the stable browser environment, not stored on the device**, which is why it survives a cookie clear while the `cookieID` does not. The [Identifiers](/features/identification) page lays out how the ids relate.

## Where your data is stored

ShieldLabs processes and stores identification data in its own infrastructure, in a single region. There is no per-customer data-residency or region selection today, so you cannot pin storage to a specific country or cloud. Identification records are retained for **up to 12 months**; you can export them or request earlier deletion at any time. If you have a specific residency or retention requirement, email **[contact@shieldlabs.ai](mailto:contact@shieldlabs.ai)**.

## You control retention

Your data is yours to read, export, and remove.

<CardGroup cols={2}>
  <Card title="Export" icon="download" href="/features/traffic-analytics">
    Filter the Data table on the dashboard and export the matching records as CSV. Exports are free and do not consume requests.
  </Card>

  <Card title="Read programmatically" icon="code" href="/api/server-api">
    Pull snapshots for any identifier through the History API, keyed by IP, VisitorID, DeviceID, UserHID, RequestID, SessionID, or CookieID.
  </Card>
</CardGroup>

Deletion is request-based: there is no self-serve delete endpoint today, so to remove stored records, or for any other data-handling question, email **[contact@shieldlabs.ai](mailto:contact@shieldlabs.ai)**.

## Data minimization in practice

The design choices above all point the same way: collect the technical signals needed to identify a browser and score anonymity, and nothing that identifies a person.

* Identifiers are **derived** (DeviceID, VisitorID) or **pseudonymous** (UserHID, supplied hashed by you), never tied to a name or email by ShieldLabs.
* The public `IP` and the device's local IP are kept distinct, and the local IP correlation field stays server-side.
* The snippet captures the **current** page URL and referrer for attribution, not a browsing trail.
* No passwords, payment data, or form contents are ever read.

## Related

* [Security](/security): webhook signature verification, key management, and transport.
* [Identifiers](/features/identification): how RequestID, DeviceID, VisitorID, and UserHID are built and how durable each one is.
* [Signals](/features/anonymity-signals): the full signal and scoring reference.
* [Server API](/api/server-api): export and query your stored snapshots.
