chrome.storage

Description

Use thechrome.storage API to store, retrieve, and track changes to user data.

Permissions

storage

To use the storage API, declare the"storage" permission in the extensionmanifest. 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, andStorage), but was designed to meet the storage needs of extensions. The following are a few key features:

  • All extension contexts, including the extension service worker and content scripts have access to the Storage API.
  • The JSON serializable values are stored as object properties.
  • The Storage API is asynchronous with bulk read and write operations.
  • Even if the user clears the cache and browsing history, the data persists.
  • Stored settings persist even when usingsplit incognito.
  • Includes an exclusive read-onlymanaged storage area for enterprise policies.

Can extensions use web storage APIs?

While extensions can use theStorage interface (accessible fromwindow.localStorage) in some contexts (popup and other HTML pages), we don't recommend it for the following reasons:

  • Extension service workers can't use the Web Storage API.
  • Content scripts share storage with the host page.
  • Data saved using the Web Storage API is lost when the user clears their browsing history.

To move data from web storage APIs to extension storage APIs from a service worker:

  1. Prepare an offscreen document html page and script file. The script file should contain a conversion routine and anonMessage handler.
  2. In the extension service worker, checkchrome.storage for your data.
  3. If your data isn't found, callcreateDocument().
  4. After the returned Promise resolves, callsendMessage() to start the conversion routine.
  5. Inside the offscreen document'sonMessage handler, call the conversion routine.

There are also some nuances to how web storage APIs work in extensions. Learn more in theStorage and Cookies article.

Storage areas

The Storage API is divided into the following storage areas:

storage.local
Data is stored locally and cleared when the extension is removed. The storage limit is 10 MB (5 MB in Chrome 113 and earlier), but can be increased by requesting the"unlimitedStorage" permission. We recommend usingstorage.local to store larger amounts of data. By default, it's exposed to content scripts, but this behavior can be changed by callingchrome.storage.local.setAccessLevel().
storage.managed
Managed storage is read-only storage for policy installed extensions and managed by system administrators using a developer-defined schema and enterprise policies. Policies are analogous to options but are configured by a system administrator instead of the user, allowing the extension to be preconfigured for all users of an organization. For information on policies, seeDocumentation for Administrators. To learn more about themanaged storage area, seeManifest for storage areas.
storage.session
Holds data in memory while an extension is loaded. The storage is cleared if the extension is disabled, reloaded or updated and when the browser restarts. By default, it's not exposed to content scripts, but this behavior can be changed by callingchrome.storage.session.setAccessLevel(). The storage limit is 10 MB (1 MB in Chrome 111 and earlier). Thestorage.session interface is one of severalwe recommend for service workers.
storage.sync
If syncing is enabled, the data is synced to any Chrome browser that the user is logged into. If disabled, it behaves likestorage.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 usingstorage.sync to preserve user settings across synced browsers. If you're working with sensitive user data, instead usestorage.session. By default,storage.sync is exposed to content scripts, but this behavior can be changed by callingchrome.storage.sync.setAccessLevel().

Storage and throttling limits

The Storage API has the following usage limitations:

  • Storing data often comes with performance costs, and the API includes storage quotas. We recommend being careful about what data you store so that you don't lose the ability to store data.
  • Storage can take time to complete. Make sure to structure your code to account for that time.

For details on storage area limitations and what happens when they're exceeded, see the quota information forsync,local, andsession.

Use cases

The following sections demonstrate common use cases for the Storage API.

Respond to storage updates

To track changes made to storage, add a listener to itsonChanged 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}]ofObject.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 anoptions page thatallows the user to toggle a "debug mode" (implementation not shown here). The options page immediately saves the new settings tostorage.sync, and the service worker usesstorage.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>  <label for="debug">    <input type="checkbox" name="debug">    Enable debug mode  </label></form>

options.js:

// In-page cache of the user's optionsconstoptions={};constoptionsForm=document.getElementById("optionsForm");// Immediately persist options changesoptionsForm.debug.addEventListener("change",(event)=>{options.debug=event.target.checked;chrome.storage.sync.set({options});});// Initialize the form with the user's option settingsconstdata=awaitchrome.storage.sync.get("options");Object.assign(options,data.options);optionsForm.debug.checked=Boolean(options.debug);

background.js:

functionsetDebugMode(){/* ... */}// Watch for changes to the user's options & apply themchrome.storage.onChanged.addListener((changes,area)=>{if(area==='sync' &&changes.options?.newValue){constdebugMode=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 toasynchronously load data from storage before they execute their event handlers. To do this, thefollowing snippet uses an asyncaction.onClicked event handler that waits for thestorageCacheglobal to be populated before executing its logic.

background.js:

// Where we will expose all the data we retrieve from storage.sync.conststorageCache={count:0};// Asynchronously retrieve data from storage.sync, then cache it.constinitStorageCache=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{awaitinitStorageCache;}catch(e){// Handle error that occurred during storage initialization.}// Normal action handler logic.storageCache.count++;storageCache.lastTabId=tab.id;chrome.storage.sync.set(storageCache);});

DevTools

You can view and edit data stored using the API in DevTools. To learn more, seetheView and edit extension storagepage in the DevTools documentation.

Examples

The following samples demonstrate thelocal,sync, andsession storage areas:

Local

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

AccessLevel

Chrome 102+

The 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.

StorageArea

Properties

  • onChanged

    Event<functionvoidvoid>

    Chrome 73+

    Fired when one or more items change.

    TheonChanged.addListener function looks like:

    (callback: function) => {...}

    • callback

      function

      Thecallback parameter looks like:

      (changes: object) => void

      • changes

        object

  • clear

    void

    Promise

    Removes all items from storage.

    Theclear function looks like:

    (callback?: function) => {...}

    • callback

      function optional

      Thecallback parameter looks like:

      () => void

    • returns

      Promise<void>

      Chrome 95+

      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.

  • get

    void

    Promise

    Gets one or more items from storage.

    Theget 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 innull to get the entire contents of storage.

    • callback

      function optional

      Thecallback parameter looks like:

      (items: object) => void

      • items

        object

        Object with items in their key-value mappings.

    • returns

      Promise<object>

      Chrome 95+

      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.

  • getBytesInUse

    void

    Promise

    Gets the amount of space (in bytes) being used by one or more items.

    ThegetBytesInUse 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 innull to get the total usage of all of storage.

    • callback

      function optional

      Thecallback parameter looks like:

      (bytesInUse: number) => void

      • bytesInUse

        number

        Amount of space being used in storage, in bytes.

    • returns

      Promise<number>

      Chrome 95+

      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.

  • getKeys

    void

    PromiseChrome 130+

    Gets all keys from storage.

    ThegetKeys function looks like:

    (callback?: function) => {...}

    • callback

      function optional

      Thecallback parameter looks like:

      (keys: string[]) => void

      • keys

        string[]

        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.

  • remove

    void

    Promise

    Removes one or more items from storage.

    Theremove function looks like:

    (keys: string | string[], callback?: function) => {...}

    • keys

      string | string[]

      A single key or a list of keys for items to remove.

    • callback

      function optional

      Thecallback parameter looks like:

      () => void

    • returns

      Promise<void>

      Chrome 95+

      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.

  • set

    void

    Promise

    Sets multiple items.

    Theset function looks like:

    (items: object, callback?: function) => {...}

    • items

      object

      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 atypeof"object" and"function" will typically serialize to{}, with the exception ofArray (serializes as expected),Date, andRegex (serialize using theirString representation).

    • callback

      function optional

      Thecallback parameter looks like:

      () => void

    • returns

      Promise<void>

      Chrome 95+

      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.

  • setAccessLevel

    void

    PromiseChrome 102+

    Sets the desired access level for the storage area. By default,session storage is restricted to trusted contexts (extension pages and service workers), whilelocal andsync storage allow access from both trusted and untrusted contexts.

    ThesetAccessLevel function looks like:

    (accessOptions: object, callback?: function) => {...}

    • accessOptions

      object

      • accessLevel

        The access level of the storage area.

    • callback

      function optional

      Thecallback parameter looks like:

      () => void

    • returns

      Promise<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.

StorageChange

Properties

  • newValue

    any optional

    The new value of the item, if there is a new value.

  • oldValue

    any optional

    The old value of the item, if there was an old value.

Properties

local

Items in thelocal storage area are local to each machine.

Type

StorageArea & object

Properties

  • QUOTA_BYTES

    10485760

    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 theunlimitedStorage permission. Updates that would cause this limit to be exceeded fail immediately and setruntime.lastError when using a callback, or a rejected Promise if using async/await.

managed

Items in themanaged 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, seeManifest for storage areas.

session

Chrome 102+MV3+

Items in thesession storage area are stored in-memory and will not be persisted to disk.

Type

StorageArea & object

Properties

  • QUOTA_BYTES

    10485760

    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 setruntime.lastError when using a callback, or when a Promise is rejected.

sync

Items in thesync storage area are synced using Chrome Sync.

Type

StorageArea & object

Properties

  • MAX_ITEMS

    512

    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 setruntime.lastError when using a callback, or when a Promise is rejected.

  • MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE

    1000000

    Deprecated

    The storage.sync API no longer has a sustained write operation quota.

  • MAX_WRITE_OPERATIONS_PER_HOUR

    1800

    The maximum number ofset,remove, orclear 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 setruntime.lastError when using a callback, or when a Promise is rejected.

  • MAX_WRITE_OPERATIONS_PER_MINUTE

    120

    The maximum number ofset,remove, orclear 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 setruntime.lastError when using a callback, or when a Promise is rejected.

  • QUOTA_BYTES

    102400

    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 setruntime.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 setruntime.lastError when using a callback, or when a Promise is rejected.

Events

onChanged

chrome.storage.onChanged.addListener(
  callback: function,
)

Fired when one or more items change.

Parameters

  • callback

    function

    Thecallback parameter looks like:

    (changes: object, areaName: string) => void

    • changes

      object

    • areaName

      string

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-07-11 UTC.