Stay organized with collections Save and categorize content based on your preferences.
DescriptionUse the chrome.storage
API to store, retrieve, and track changes to user data.
storage
To use the storage API, declare the "storage"
permission in the extension manifest. For example:
{
"name": "My extension",
...
"permissions": [
"storage"
],
...
}
Concepts and usage
The Storage API provides an extension-specific way to persist user data and state. It's similar to the web platform's storage APIs (IndexedDB, and Storage), but was designed to meet the storage needs of extensions. The following are a few key features:
While extensions can use the Storage
interface (accessible from window.localStorage
) in some contexts (popup and other HTML pages), we don't recommend it for the following reasons:
To move data from web storage APIs to extension storage APIs from a service worker:
onMessage
handler.chrome.storage
for your data.createDocument()
.sendMessage()
to start the conversion routine.onMessage
handler, call the conversion routine.There are also some nuances to how web storage APIs work in extensions. Learn more in the Storage and Cookies article.
Storage areasThe Storage API is divided into the following storage areas:
storage.local
"unlimitedStorage"
permission. We recommend using storage.local
to store larger amounts of data. By default, it's exposed to content scripts, but this behavior can be changed by calling chrome.storage.local.setAccessLevel()
.
storage.managed
managed
storage area, see Manifest for storage areas.
storage.session
chrome.storage.session.setAccessLevel()
. The storage limit is 10 MB (1 MB in Chrome 111 and earlier). Thestorage.session
interface is one of several we recommend for service workers.
storage.sync
storage.local
. Chrome stores the data locally when the browser is offline and resumes syncing when it's back online. The quota limitation is approximately 100 KB, 8 KB per item. We recommend using storage.sync
to preserve user settings across synced browsers. If you're working with sensitive user data, instead use storage.session
. By default, storage.sync
is exposed to content scripts, but this behavior can be changed by calling chrome.storage.sync.setAccessLevel()
.
The Storage API has the following usage limitations:
For details on storage area limitations and what happens when they're exceeded, see the quota information for sync
, local
, and session
.
The following sections demonstrate common use cases for the Storage API.
Respond to storage updatesTo track changes made to storage, add a listener to its onChanged
event. When anything changes in storage, that event fires. The sample code listens for these changes:
background.js:
chrome.storage.onChanged.addListener((changes, namespace) => {
for (let [key, { oldValue, newValue }] of Object.entries(changes)) {
console.log(
`Storage key "${key}" in namespace "${namespace}" changed.`,
`Old value was "${oldValue}", new value is "${newValue}".`
);
}
});
We can take this idea even further. In this example, we have an options page that allows the user to toggle a "debug mode" (implementation not shown here). The options page immediately saves the new settings to storage.sync
, and the service worker uses storage.onChanged
to apply the setting as soon as possible.
options.html:
<!-- type="module" allows you to use top level await -->
<script defer src="options.js" type="module"></script>
<form id="optionsForm">
<label for="debug">
<input type="checkbox" name="debug" id="debug">
Enable debug mode
</label>
</form>
options.js:
// In-page cache of the user's options
const options = {};
const optionsForm = document.getElementById("optionsForm");
// Immediately persist options changes
optionsForm.debug.addEventListener("change", (event) => {
options.debug = event.target.checked;
chrome.storage.sync.set({ options });
});
// Initialize the form with the user's option settings
const data = await chrome.storage.sync.get("options");
Object.assign(options, data.options);
optionsForm.debug.checked = Boolean(options.debug);
background.js:
function setDebugMode() { /* ... */ }
// Watch for changes to the user's options & apply them
chrome.storage.onChanged.addListener((changes, area) => {
if (area === 'sync' && changes.options?.newValue) {
const debugMode = Boolean(changes.options.newValue.debug);
console.log('enable debug mode?', debugMode);
setDebugMode(debugMode);
}
});
Asynchronous preload from storage
Because service workers don't run all the time, Manifest V3 extensions sometimes need to asynchronously load data from storage before they execute their event handlers. To do this, the following snippet uses an async action.onClicked
event handler that waits for the storageCache
global to be populated before executing its logic.
background.js:
// Where we will expose all the data we retrieve from storage.sync.
const storageCache = { count: 0 };
// Asynchronously retrieve data from storage.sync, then cache it.
const initStorageCache = chrome.storage.sync.get().then((items) => {
// Copy the data retrieved from storage into storageCache.
Object.assign(storageCache, items);
});
chrome.action.onClicked.addListener(async (tab) => {
try {
await initStorageCache;
} catch (e) {
// Handle error that occurred during storage initialization.
}
// Normal action handler logic.
storageCache.count++;
storageCache.lastTabId = tab.id;
chrome.storage.sync.set(storageCache);
});
You can view and edit data stored using the API in DevTools. To learn more, see the View and edit extension storage page in the DevTools documentation.
ExamplesThe following samples demonstrate the local
, sync
, and session
storage areas:
chrome.storage.local.set({ key: value }).then(() => {
console.log("Value is set");
});
chrome.storage.local.get(["key"]).then((result) => {
console.log("Value is " + result.key);
});
Sync
chrome.storage.sync.set({ key: value }).then(() => {
console.log("Value is set");
});
chrome.storage.sync.get(["key"]).then((result) => {
console.log("Value is " + result.key);
});
Session
chrome.storage.session.set({ key: value }).then(() => {
console.log("Value was set");
});
chrome.storage.session.get(["key"]).then((result) => {
console.log("Value is " + result.key);
});
To see other demos of the Storage API, explore any of the following samples:
Types AccessLevelThe storage area's access level.
Enum"TRUSTED_CONTEXTS"
Specifies contexts originating from the extension itself.
"TRUSTED_AND_UNTRUSTED_CONTEXTS"
Specifies contexts originating from outside the extension.
onChanged
Event<functionvoidvoid>
Fired when one or more items change.
The onChanged.addListener
function looks like:
(callback: function) => {...}
The callback
parameter looks like:
(changes: object) => void
Removes all items from storage.
The clear
function looks like:
(callback?: function) => {...}
callback
function optional
The callback
parameter looks like:
() => void
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
Gets one or more items from storage.
The get
function looks like:
(keys?: string | string[] | object, callback?: function) => {...}
keys
string | string[] | object optional
A single key to get, list of keys to get, or a dictionary specifying default values (see description of the object). An empty list or object will return an empty result object. Pass in null
to get the entire contents of storage.
callback
function optional
The callback
parameter looks like:
(items: object) => void
Object with items in their key-value mappings.
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
Gets the amount of space (in bytes) being used by one or more items.
The getBytesInUse
function looks like:
(keys?: string | string[], callback?: function) => {...}
keys
string | string[] optional
A single key or list of keys to get the total usage for. An empty list will return 0. Pass in null
to get the total usage of all of storage.
callback
function optional
The callback
parameter looks like:
(bytesInUse: number) => void
Amount of space being used in storage, in bytes.
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
Gets all keys from storage.
The getKeys
function looks like:
(callback?: function) => {...}
callback
function optional
The callback
parameter looks like:
(keys: string[]) => void
Array with keys read from storage.
returns
Promise<string[]>
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
Removes one or more items from storage.
The remove
function looks like:
(keys: string | string[], callback?: function) => {...}
A single key or a list of keys for items to remove.
callback
function optional
The callback
parameter looks like:
() => void
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
Sets multiple items.
The set
function looks like:
(items: object, callback?: function) => {...}
An object which gives each key/value pair to update storage with. Any other key/value pairs in storage will not be affected.
Primitive values such as numbers will serialize as expected. Values with a typeof
"object"
and "function"
will typically serialize to {}
, with the exception of Array
(serializes as expected), Date
, and Regex
(serialize using their String
representation).
callback
function optional
The callback
parameter looks like:
() => void
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
Sets the desired access level for the storage area. By default, session
storage is restricted to trusted contexts (extension pages and service workers), while local
and sync
storage allow access from both trusted and untrusted contexts.
The setAccessLevel
function looks like:
(accessOptions: object, callback?: function) => {...}
The access level of the storage area.
callback
function optional
The callback
parameter looks like:
() => void
Promises are supported in Manifest V3 and later, but callbacks are provided for backward compatibility. You cannot use both on the same function call. The promise resolves with the same type that is passed to the callback.
The new value of the item, if there is a new value.
The old value of the item, if there was an old value.
Items in the local
storage area are local to each machine.
The maximum amount (in bytes) of data that can be stored in local storage, as measured by the JSON stringification of every value plus every key's length. This value will be ignored if the extension has the unlimitedStorage
permission. Updates that would cause this limit to be exceeded fail immediately and set runtime.lastError
when using a callback, or a rejected Promise if using async/await.
Items in the managed
storage area are set by an enterprise policy configured by the domain administrator, and are read-only for the extension; trying to modify this namespace results in an error. For information on configuring a policy, see Manifest for storage areas.
Items in the session
storage area are stored in-memory and will not be persisted to disk.
The maximum amount (in bytes) of data that can be stored in memory, as measured by estimating the dynamically allocated memory usage of every value and key. Updates that would cause this limit to be exceeded fail immediately and set runtime.lastError
when using a callback, or when a Promise is rejected.
Items in the sync
storage area are synced using Chrome Sync.
The maximum number of items that can be stored in sync storage. Updates that would cause this limit to be exceeded will fail immediately and set runtime.lastError
when using a callback, or when a Promise is rejected.
MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE
1000000
The storage.sync API no longer has a sustained write operation quota.
MAX_WRITE_OPERATIONS_PER_HOUR
1800
The maximum number of set
, remove
, or clear
operations that can be performed each hour. This is 1 every 2 seconds, a lower ceiling than the short term higher writes-per-minute limit.
Updates that would cause this limit to be exceeded fail immediately and set runtime.lastError
when using a callback, or when a Promise is rejected.
MAX_WRITE_OPERATIONS_PER_MINUTE
120
The maximum number of set
, remove
, or clear
operations that can be performed each minute. This is 2 per second, providing higher throughput than writes-per-hour over a shorter period of time.
Updates that would cause this limit to be exceeded fail immediately and set runtime.lastError
when using a callback, or when a Promise is rejected.
The maximum total amount (in bytes) of data that can be stored in sync storage, as measured by the JSON stringification of every value plus every key's length. Updates that would cause this limit to be exceeded fail immediately and set runtime.lastError
when using a callback, or when a Promise is rejected.
QUOTA_BYTES_PER_ITEM
8192
The maximum size (in bytes) of each individual item in sync storage, as measured by the JSON stringification of its value plus its key length. Updates containing items larger than this limit will fail immediately and set runtime.lastError
when using a callback, or when a Promise is rejected.
chrome.storage.onChanged.addListener(
callback: function,
)
Fired when one or more items change.
ParametersThe callback
parameter looks like:
(changes: object, areaName: string) => void
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-07-11 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-07-11 UTC."],[],[]]
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4