chrome.storage API Tutorial: Save Extension Data
How to persist settings and user data in a Chrome extension with chrome.storage — including sync vs local and quota limits.

Extensions cannot rely on localStorage inside a service worker, so chrome.storage is the standard way to persist data. It is asynchronous, available in every extension surface, and shared across the popup, options page, content scripts and background worker.
Which area should you use?
- chrome.storage.sync — small user settings that follow the signed-in profile. ~100KB total, 8KB per item.
- chrome.storage.local — bigger local-only data, roughly 10MB (more with unlimitedStorage).
- chrome.storage.session — in-memory data cleared when the browser closes; good for tokens.
Reading and writing
Add "storage" to permissions, then: await chrome.storage.sync.set({ theme: "dark" }) and const { theme } = await chrome.storage.sync.get({ theme: "light" }). Passing an object to get gives you defaults for free.
Reacting to changes
chrome.storage.onChanged.addListener((changes, area) => ...) fires in every surface, which is the cleanest way to keep a popup and a content script in sync without custom messaging.
When to use something else
For thousands of records, full-text search or blobs, use IndexedDB in the service worker. Keep chrome.storage for settings and small state.
Frequently asked questions
Is chrome.storage encrypted?
No. It is stored on disk in the profile directory. Never keep secrets you would not want a local user to read; move real credentials to a backend.
Why is my chrome.storage.sync write failing?
You likely exceeded the 8KB per-item or 100KB total quota, or the write-per-minute limit. Switch that key to chrome.storage.local.