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 mode is the browser feature that opens a clean, temporary window - history and cookies do not stick around after you close it. The catch is that private mode also changes how the browser stores data: the storage allowance (quota) shrinks, some data-saving APIs are turned off or act differently, and nothing survives the session. Websites probe these differences (in the past through the FileSystem API, now mainly through the storage quota reported by navigator.storage.estimate() and how IndexedDB behaves) to gate content or to score how risky a visitor looks - because automated and abusive traffic shows up in private sessions far more often than in normal ones.

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 mode isolates and shrinks the browser's storage, and that is exactly what gives it away. The classic Chrome tell was window.webkitRequestFileSystem, an API that returned an error in incognito but worked normally otherwise - a single function call was enough to tell the difference. Google closed that gap, so detection moved to the storage quota: navigator.storage.estimate() (an API that tells a page how much space it may use) reports a much smaller quota in private mode - capped to a small fraction of disk, or to a fixed ceiling - than a normal session would on the same machine. Compare that reported quota against how big the device looks, and the mode shows through.

Other differences have been used over the years: IndexedDB (the browser's built-in database) throwing errors or acting differently, the Quota API's temporary-versus-persistent storage limits, and service-worker or cache data not surviving the session. Each browser release tends to patch whichever tell is currently popular, so the exact probe in use keeps shifting - but the underlying fact, that private mode constrains storage, keeps producing new ones.

Why sites detect it at all

There are two motivations. Risk scoring: abusive and automated traffic is disproportionately private, because scrapers and fraud tools default to fresh, stateless sessions - no saved cookies or history - to avoid carrying identifiers between visits. Incognito alone is not proof of a bot, since plenty of real people browse privately, so it is used as a soft signal folded into a broader risk 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 free-article count by opening a private window. This is the same plumbing the anti-bot use case relies on, which is why incognito detection turns 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 (the on-disk folder that holds a browser profile) reports normal storage. But several stealth setups do use private contexts or throwaway 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: the storage quota should match the kind of device you are claiming to be, and the persistence behaviour should look like 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 (its on-disk profile folder) reports normal storage quotas and is not in private mode. But some stealth setups deliberately use throwaway 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 people from resetting their free-article count). 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 the 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-31