Inspecting and Editing Extension Storage
See and change what an MV3 extension has stored: the DevTools Application panel for chrome.storage, IndexedDB and Cache Storage, console snippets for local, sync and session areas, watching changes live, seeding test data and resetting state.
Table of Contents
- Where extension data lives
- Step-by-step: inspecting and changing storage
- Common mistakes
- Cross-browser variation
- Verification
- FAQ
- Can I edit chrome.storage from the web page’s DevTools?
- Does the viewer update live?
- How do I inspect another profile’s storage?
- Is it safe to leave a debug storage viewer in the options page?
- Can I inspect storage of an extension installed from the store?
- How do I compare storage between two versions?
- Does editing storage in DevTools fire onChanged?
- Related
A bug report says “my settings reset after the update”. To investigate you need to see exactly what is in chrome.storage.sync and local before and after, change a value to reproduce an edge case, and maybe wipe everything to test a fresh install without reinstalling. Extension storage is spread across several areas — chrome.storage.local, sync, session and managed, plus IndexedDB, Cache Storage and localStorage in extension pages — and each is inspected slightly differently. DevTools has a viewer for most of them, and a few console snippets cover the rest. This guide shows both. It belongs to debugging extension contexts.
Where extension data lives
chrome.storage areas are owned by the extension, not by any one page, so they can be inspected from any extension context’s DevTools — the service worker is the most convenient because it is always available from chrome://extensions. Chrome’s DevTools Application panel shows an Extension storage section for local, sync, session and managed when DevTools is attached to an extension context. IndexedDB, Cache Storage and localStorage belong to the extension’s origin (chrome-extension://<id>) and appear under their usual Application panel headings. Content scripts run in the page’s origin, so the page’s IndexedDB and localStorage are the page’s, not the extension’s.
Step-by-step: inspecting and changing storage
1. Open DevTools on an extension context
On chrome://extensions, enable Developer mode and click the service worker link under the extension (or right-click the popup and choose Inspect). In that DevTools window, open Application → Storage → Extension storage and choose Local, Sync, Session or Managed. The viewer lists keys and JSON values, and you can edit or delete entries in place.
2. Dump storage from the console
1// Run in the service worker's DevTools console
2await chrome.storage.local.get(null);
3await chrome.storage.sync.get(null);
4await chrome.storage.session.get(null);
5console.table(Object.entries(await chrome.storage.local.get(null)).map(([k, v]) => ({ key: k, bytes: JSON.stringify(v).length })));
Execution context: the service worker console (top-level await works there). get(null) returns everything in an area. The table of approximate sizes per key quickly shows what is filling the quota; compare with getBytesInUse as in watching storage usage with getBytesInUse.
3. Watch changes as they happen
1// Service worker console — logs every write from any context
2chrome.storage.onChanged.addListener((changes, area) => {
3 for (const [key, { oldValue, newValue }] of Object.entries(changes)) {
4 console.log(`%c${area}%c ${key}`, "color:#7c3aed", "color:inherit", { oldValue, newValue });
5 }
6});
Execution context: the service worker console. Every write from the popup, options page, content scripts or the worker itself appears with old and new values — the quickest way to find which code path overwrote a setting. The listener lives until the worker stops; re-run it after a restart, or add it permanently behind a debug flag. See logging across contexts without losing messages.
4. Edit values to reproduce edge cases
1await chrome.storage.sync.set({ schemaVersion: 2 }); // pretend we're on an old schema
2await chrome.storage.local.set({ items: Array.from({ length: 5000 }, (_, i) => ({ id: i, title: `Item ${i}` })) });
3await chrome.storage.local.remove("lastSyncAt"); // simulate never having synced
Execution context: the service worker console. Setting an old schema version and then triggering onInstalled with reason update (by reloading the extension) exercises migrations; large fixtures test performance; removing keys simulates first-run paths. See migrating IndexedDB schemas on update.
5. Snapshot and restore
1// Snapshot
2copy(JSON.stringify({ local: await chrome.storage.local.get(null), sync: await chrome.storage.sync.get(null) }, null, 2));
3
4// Restore (paste the JSON into `snap`)
5await chrome.storage.local.clear(); await chrome.storage.local.set(snap.local);
6await chrome.storage.sync.clear(); await chrome.storage.sync.set(snap.sync);
Execution context: the service worker console. copy() is a DevTools console utility that puts a string on the clipboard. Snapshots let you reset to a known state between experiments, and users can send one with a bug report if you give them a “Copy diagnostics” button that does the same (excluding secrets).
6. Reset to a fresh install without reinstalling
1await Promise.all([chrome.storage.local.clear(), chrome.storage.sync.clear(), chrome.storage.session.clear()]);
2indexedDB.databases().then((dbs) => dbs.forEach((d) => indexedDB.deleteDatabase(d.name)));
3(await caches.keys()).forEach((k) => caches.delete(k));
4chrome.runtime.reload();
Execution context: the service worker console. Clearing every area and reloading reproduces a clean state much faster than removing and re-adding the extension — but note onInstalled will report update, not install. For a true first-install test, remove and reload the unpacked extension. Clearing sync also clears it on other devices signed in to the same profile, so use a test profile.
7. Inspect IndexedDB
Under Application → IndexedDB → chrome-extension://<id>, DevTools lists databases, object stores and records, with filtering by key range and a refresh button. Records can be deleted but not edited in place; for edits, use a console snippet with your IndexedDB wrapper. See keeping IndexedDB fast in an extension.
8. Inspect managed storage
chrome.storage.managed is read-only and comes from enterprise policy. To test it, set policy locally (on Linux, a JSON file under /etc/opt/chrome/policies/managed/; on macOS and Windows, platform policy tools) and check chrome://policy to confirm Chrome loaded it. See configuring extensions with enterprise managed storage.
Common mistakes
- Inspecting the web page’s storage. Content scripts see the page’s, not the extension’s.
- Clearing
syncin your main profile. It syncs to your other devices. - Expecting
installafterclear()+ reload. It reportsupdate. - Forgetting
sessionis in memory. It is empty after a browser restart. - Debug listeners lost on worker restart. Re-run or add behind a flag.
Cross-browser variation
- Chrome / Edge: Application panel → Extension storage for all
chrome.storageareas. - Firefox:
about:debugging→ Inspect → Storage tab shows “Extension Storage” forlocal;syncandsessionare read from the console. - Safari: Web Inspector for the extension’s background page shows Storage;
browser.storageareas are best read from the console.
Verification
- Write a value from the popup and confirm it appears in the viewer and the
onChangedlogger. - Snapshot, change several keys, restore, and confirm the original state returns.
- Reset everything and confirm the extension shows its first-run state.
- Confirm IndexedDB databases appear under the extension origin.
FAQ
Can I edit chrome.storage from the web page’s DevTools?
No. Open DevTools for an extension context instead.
Does the viewer update live?
It refreshes when you reopen it or click refresh; for live changes use the onChanged logger.
How do I inspect another profile’s storage?
Load the extension in that profile and inspect from there — storage is per profile.
Is it safe to leave a debug storage viewer in the options page?
Hide it behind a developer flag and never display secrets such as tokens. A read-only “Copy diagnostics” button that redacts sensitive keys is useful for support without exposing data.
Can I inspect storage of an extension installed from the store?
Yes. Enable Developer mode and use the service worker’s Inspect link; store-installed extensions can be inspected the same way as unpacked ones.
How do I compare storage between two versions?
Take a snapshot before updating, another after, and diff the two JSON files. Key renames and dropped fields from migrations show up immediately.
Does editing storage in DevTools fire onChanged?
Yes. Edits made through the viewer or the console go through the same storage API, so every open context receives storage.onChanged and reacts as it would to a real change.
Related
- Finding the right DevTools target for each context — which DevTools to open.
- Tracing messages between contexts — who wrote what.
- Resolving concurrent writes in chrome.storage — when values flip.
- Debugging extension contexts — the parent topic.