Implementation of Data Storage (chrome.storage) in Browser Extension
chrome.storage is the only reliable way to store data in extension. localStorage is technically available in popup and options page, but not in service worker, and doesn't sync between extension contexts. chrome.storage works everywhere.
Three storage types
chrome.storage.local — stored locally, up to 10 MB (without unlimitedStorage permission). Main choice for cached data, user content.
chrome.storage.sync — syncs across user's devices via Google account, up to 100 KB / 8 KB per key. For settings.
chrome.storage.session — memory only, cleared on browser close. In MV3 — for temporary SW state that survives its restart (unlike variables), but not browser restart.
Basic operations
// Write
await chrome.storage.local.set({
userData: { id: 42, name: 'Alex' },
lastFetch: Date.now(),
items: [1, 2, 3]
});
// Read with defaults
const result = await chrome.storage.local.get({
userData: null,
lastFetch: 0,
items: []
});
console.log(result.userData); // { id: 42, name: 'Alex' } or null
// Read by key
const { settings } = await chrome.storage.sync.get('settings');
// Delete
await chrome.storage.local.remove(['lastFetch', 'tmpData']);
// Clear all
await chrome.storage.local.clear();
Subscribe to changes
chrome.storage.onChanged.addListener((changes, areaName) => {
if (areaName !== 'sync') return;
if ('theme' in changes) {
const { oldValue, newValue } = changes.theme;
console.log(`Theme changed: ${oldValue} → ${newValue}`);
applyTheme(newValue);
}
});
This works in all extension contexts — content script also gets event if subscribed.
Typed storage wrapper utility
In real extension, convenient to make typed wrapper:
// storage/store.ts
type Settings = {
theme: 'light' | 'dark' | 'system';
targetLang: string;
autoTranslate: boolean;
};
const defaultSettings: Settings = {
theme: 'system',
targetLang: 'en',
autoTranslate: false,
};
export const settingsStore = {
async get(): Promise<Settings> {
const result = await chrome.storage.sync.get('settings');
return { ...defaultSettings, ...result.settings };
},
async set(settings: Settings): Promise<void> {
await chrome.storage.sync.set({ settings });
},
};
Timeline
Simple get/set: 1 day. Complex store with listeners, migrations: 2–3 days.







