Anti-Bot

What Is Incognito / Private Mode Detection?

What Is Incognito / Private Mode Detection? — conceptual illustration
On this page

Incognito detection is the set of techniques that reveal whether a browser is in private / incognito mode. Private modes change how storage behaves - quotas shrink, some persistence APIs are disabled or behave differently, and data does not survive the session. Sites probe these differences (historically via the FileSystem API, now mainly via navigator.storage.estimate() quota and IndexedDB/persistence behaviour) to gate content or to score risk, because automated and abusive traffic is over-represented in private sessions.

Quick facts

ProbesStorage quota (navigator.storage.estimate), IndexedDB, persistence APIs
Old methodwindow.requestFileSystem was disabled in Chrome incognito (now removed)
Current tellReduced/quantized storage quota relative to disk size
Why sites careBots and abuse skew toward private sessions; used for risk scoring + paywalls
Arms raceBrowsers actively close these tells; detection shifts each release

How private mode leaks

Private modes isolate and shrink storage, and that is what gives them away. The historical Chrome tell was the window.webkitRequestFileSystem API, which returned an error in incognito and worked normally otherwise - a one-call check. Google closed that, and detection moved to storage quota: navigator.storage.estimate() reports a much smaller quota in private mode (capped to a fraction of disk, or to a fixed ceiling) than in a normal session on the same machine. Comparing the reported quota against the device's apparent capacity reveals the mode.

Other differences have been used over time: IndexedDB throwing or behaving differently, the Quota API's temporary-vs-persistent storage limits, and service-worker/cache persistence not surviving. Each browser release tends to close the current tell, so the specific probe in use drifts, but the underlying fact - private mode constrains storage - keeps regenerating new ones.

Why sites detect it at all

Two motivations. Risk scoring: abusive and automated traffic is disproportionately private, because scrapers and fraud tooling default to fresh, stateless sessions to avoid carrying identifiers. Incognito alone is not proof of a bot - plenty of real users browse privately - so it is a soft signal folded into a broader score, not a standalone block.

The other motivation is business logic: metered paywalls (news sites) and free-trial limits historically used incognito detection to stop readers from resetting their article count by opening a private window. This is the same plumbing the anti-bot use case relies on, which is why incognito detection shows up both in paywall scripts and in fraud/bot stacks.

Implications for scrapers

For scraping, the practical lesson is that running headless does not put you in incognito by default - a headless browser with a normal user-data directory reports normal storage. But several stealth setups do use private contexts or ephemeral profiles, and if the site scores incognito as risk, that choice is working against you. If a target gates on private mode, the fix is to run with a persistent profile and real storage quota so navigator.storage.estimate() looks like an ordinary install.

As always, coherence matters more than any single value: storage quota should match the claimed device class, and persistence behaviour should be consistent with a returning user if you are presenting cookies and history. Treat incognito detection as one more consistency probe in the stack rather than a special case.

Code example

javascript
// Modern incognito probe: storage quota is constrained in private mode
async function looksPrivate() {
  if (!navigator.storage || !navigator.storage.estimate) return null;
  const { quota } = await navigator.storage.estimate();
  // Normal session: quota is a large fraction of free disk (often GBs).
  // Private mode: quota is capped much lower (historically ~120MB on some builds,
  // or a small fraction of disk), so a small quota on a large device is a tell.
  return quota < 300 * 1024 * 1024;   // heuristic threshold, tuned per browser
}

// Legacy tell (removed in modern Chrome, still seen in old scripts):
//   window.webkitRequestFileSystem(0, 1, () => normal, () => incognito);

Related terms

Concept map

How Incognito Detection connects

The terms most directly tied to this one. Hover a node to see its neighbours, click to preview, drag to rearrange.

0 terms · 0 connections
You are here · Anti-Bot
Building map…

Frequently asked questions

Does running a headless scraper mean I am in incognito?

Not by default. A headless browser with a normal persistent user-data directory reports normal storage quotas and is not in private mode. But some stealth setups deliberately use ephemeral or private contexts, and if a target scores incognito as risk, that choice hurts you - run a persistent profile with real storage instead.

Is incognito detection a reliable bot signal?

On its own, no - many real users browse privately, so it is a soft signal folded into a broader risk score rather than a hard block. It became popular partly for metered paywalls (stopping article-count resets). For bot detection it is corroborating evidence, strongest when combined with other anomalies.

How do sites detect private mode now that the FileSystem trick is gone?

Mainly via storage quota: navigator.storage.estimate() returns a much smaller quota in private mode than in a normal session on the same device, so a small quota on a large machine is a tell. IndexedDB and persistence-API behaviour have also been used. Browsers keep closing specific tells, so the exact probe shifts between releases.

Last updated: 2026-05-30