What the quota used to say
navigator.storage.estimate() resolves to the origin's current usage and its quota, the amount it may store. Browsers compute the quota from the device: Chromium gives each site 60 % of the total size of the disk that holds the profile, Firefox 10 % up to 10 GiB, and Safari 60 % of the volume in browsers and 15 % in other apps, with one tenth of that for a cross-origin frame.
That made the quota a fingerprint of the disk size, and a reliable incognito test: Chromium's incognito storage lives in memory and its quota is derived from RAM, in current code physical memory times a random factor between 0.15 and 0.20, divided by three. A quota far below the disk-based value meant a private window, and incognito-detection scripts relied on exactly that for years.
Chrome's fixed reported quota
Chrome now separates the quota it enforces from the quota it reports. Sites without unlimited-storage permission are told their usage plus the smaller of 10 GiB and the disk size, in every browsing mode; the enforced limit is unchanged. Sources disagree on the first milestone that shipped it by default, but it is on in Chrome 156. We measured on a Linux machine:
- Normal profile, either of two disks: exactly 10,737,418,240 bytes (10 GiB).
- After writing 200 MiB: usage plus 10 GiB.
- Incognito context: also 10 GiB.
- With the fixed quota disabled: 575,125,787,442 bytes on a 958 GB volume and 399,486,637,670 on a 666 GB volume, which is 60 % of the total size even though the second disk had only 8.5 GB free; and 1,727,115,475 bytes in an incognito context, 0.154 times the RAM divided by three.
So in current Chrome the quota no longer reveals the disk or the mode. A Chrome 156 session that reports a disk-based quota is running an older or differently configured build.
The new tell: one flush
The same challenge widget that reads the quota also starts a worker that creates a file in the origin private file system, writes one byte through a synchronous access handle, and times flush(). In a normal profile, flushing is a real write to disk with a sync. In incognito, the file system lives in memory and flushing does nothing.
Measured in Chrome 156 with twelve flushes per run: 1 to 16 ms in a normal profile on our machine, and 0 to 0.1 ms in an incognito context, every time. The widget's result for one session is either the flush time or the error message if the file system is unavailable.
The same idea has a public history. An open-source incognito-detection library replaced its quota test with OPFS flush timing in May 2026, then replaced that in July 2026 because 8 of 18 real Android phones flushed to fast flash storage in under 0.1 ms in normal mode. On desktop the separation is clean; on phones an absolute threshold is not.
Safari and Firefox
Safari reports a device-class constant rather than the real disk size, derived from a standard volume capacity of 64 GB on iOS and 128 GB on macOS, until usage grows. When it cannot measure a volume at all, it falls back to a default per-origin quota of 1000 MiB, and a third-party frame gets one tenth of that: exactly 104,857,600 bytes. A recorded iPhone profile reports exactly that number, together with an OPFS error that reads "The operation failed for an unknown transient reason", the error Safari's private browsing produces. Both point to a private session, not a small phone; that reading comes from WebKit's source rather than a device test.
Firefox computes its quota from the total disk size, and its private windows reject the origin private file system with a security error.
The through-line
When a browser removes a signal, detection moves to the next value that depends on the same thing. The quota stopped describing the storage, so the probe now measures how the storage behaves. For automation the consequence is the usual one: the mode, the disk and the browser version have to fit together, and a profile that is new, in memory or on unusual storage shows it in more than one value. Related: the heap limit as a RAM tell and performance.now() precision, which sets the resolution of the flush measurement.
