v148 · storage · privacy
Predictable reported storage quota
Chrome 148 changes navigator.storage.estimate() to return a consistent artificial quota for sites without unlimited storage permissions, closing a channel that scripts used to detect Incognito mode.
at a glance
| Shipped in | Chrome 148 (desktop, Android, WebView) |
|---|---|
| Status | Enabled by default |
| Flag | None — on by default |
| Standards position (Firefox) | No signal |
| Standards position (Safari) | No signal |
| Blink component | Blink>Storage>Quota |
| Chromium bug | issues.chromium.org/369865059 |
| ChromeStatus | 4977371751645184 — Predictable reported storage quota |
why it exists
Before Chrome 148, navigator.storage.estimate() returned very different quota values depending on the browsing mode. In a normal window Chrome reported a quota derived from the full disk (often tens of gigabytes); in Incognito the quota was a small fixed amount (often a few hundred megabytes). Analytics and paywall libraries exploited this gap to reliably detect Incognito mode — a privacy bypass that could not be patched at the application layer.
Chrome 148 closes the gap by reporting an artificial quota equal to usage + min(10 GiB, disk rounded up to the nearest 1 GiB) in every browsing mode for sites without the unlimited-storage permission. Sites granted unlimited storage (e.g. via the persistent-storage permission) continue to receive the real hardware quota. Enforced eviction thresholds are unaffected.
shape of the API
There is no new surface. The change affects the value returned by the existing StorageManager.estimate() method.
| Property | Type | Behaviour in Chrome 148+ |
|---|---|---|
StorageEstimate.quota | number | Artificial ceiling: usage + min(10 GiB, disk ↑ 1 GiB) for limited-permission sites |
StorageEstimate.usage | number | Actual bytes used by the origin — unchanged |
example
const { usage, quota } = await navigator.storage.estimate();
// Chrome 148+: both a normal window and an Incognito window see
// the same quota for the same origin (for non-unlimited sites).
console.log(`used: ${(usage / 1e6).toFixed(1)} MB`);
console.log(`quota: ${(quota / 1e9).toFixed(1)} GB`);
// Percentage-of-used calculations remain valid; the absolute
// quota figure is now an artificial privacy-preserving value.
const pct = (usage / quota) * 100;
if (pct > 80) showStorageWarning();
// Sites granted persistent-storage permission receive the real quota:
const persisted = await navigator.storage.persisted();
// persisted === true → quota reflects actual disk capacity
Pattern from developer.chrome.com — Estimating Available Storage Space
browser support
| Browser | Support | Notes |
|---|---|---|
| Chrome 148+ | Enabled by default | Desktop, Android, WebView |
| Firefox | No signal | estimate() exists; this clamping is Chrome-specific |
| Safari | No signal | estimate() exists; this clamping is Chrome-specific |