Scrapeless Wiki

What Is IndexedDB Fingerprinting? – Definition and How It Works

Informational P3 what is indexeddb fingerprinting

Learn how IndexedDB is used for persistent identity, why databases() leaks history, and how partitioning changed it.

IndexedDB fingerprinting uses the browser's structured storage database β€” its availability, its behaviour, and what it already contains β€” for identification and persistence.

1. Two Distinct Uses

As a persistence mechanism. IndexedDB stores a written identifier that survives page reloads, tab closes, and browser restarts β€” a cookie alternative that is less commonly cleared by users who clear cookies.

As a fingerprinting surface. Its availability, quota behaviour, and error characteristics vary by browser and configuration.

The first is the more consequential in practice: IndexedDB is a favoured place to keep an identity precisely because it survives cleanup that removes cookies.

2. Database Enumeration Leaks History

const dbs = await indexedDB.databases();     // where supported
// [{name: "...", version: 1}, ...]

This lists databases for the current origin. Within a partition it reveals what this origin has stored before β€” so a returning visitor is distinguishable from a first-time one without reading any value.

For automation the reading is direct: an empty database list means a fresh profile, every single time. Real browsers accumulate databases from the sites they visit.

3. Availability and Behaviour Vary

Condition Observable
Private browsing Restricted, sometimes in-memory only
Storage blocked Open requests fail
Quota exhausted Writes fail with a quota error
Third-party context Partitioned, or unavailable
Some hardened configurations API missing entirely

An indexedDB.open() that throws or is blocked is unusual for an ordinary desktop session, which makes the error path itself a signal.

4. Storage Partitioning Changed the Game

Historically an embedded third party could read the same IndexedDB across every parent site, making it an excellent cross-site tracking vector.

Modern browsers partition storage by top-level site, so the same third party gets a separate storage bucket per parent. That largely closes cross-site tracking through IndexedDB while leaving same-site persistence intact.

The consequence for detection: a browser that does share storage across partitions is behaving in a way current browsers do not, which is itself detectable. So disabling partitioning to simplify automation is visible.

5. Quota as an Environment Probe

navigator.storage.estimate() reports a quota derived from disk space, and IndexedDB writes fail against it. That makes quota an indirect measure of the host: a tiny quota suggests a constrained container, an enormous one a server volume.

Testing the failure point is slow and conspicuous, so this is more commonly read from the estimate than probed by writing.

6. The Pristine-Profile Problem Again

The dominant automation signal here is the same one storage fingerprinting exposes: a brand-new profile has no databases, no cached data, and near-zero usage. No real browser looks like that.

The mitigation is the same: persistent profiles, one per identity, reused across runs so ordinary residue accumulates. A profile that has actually browsed looks browsed.

7. Practical Guidance

  1. Use persistent profiles rather than a fresh one per run.
  2. Do not clear IndexedDB between requests in a session; browsers do not.
  3. Do not disable storage partitioning to make automation easier β€” it is observable.
  4. Provision adequate disk in containers if quota realism matters.
  5. Treat the profile directory as a credential, since it holds identity and session state.
  6. Clear on a schedule to bound growth, not per run.

8. Summary

IndexedDB fingerprinting uses storage availability, quota, error behaviour, and database enumeration, and IndexedDB is a favoured identity-persistence mechanism because it survives cookie clearing.

Storage partitioning has largely closed its cross-site tracking use, and the main automation tell is a pristine profile with no databases and zero usage β€” so reuse persistent per-identity profiles rather than wiping storage, and do not disable partitioning, because unpartitioned behaviour is itself anomalous.