# How to Use the localStorage API in a Browser Extension: A Complete Guide

> Master the localStorage API in browser extensions. Learn how to persist data with this complete guide from Web Dev For Beginners.

- Repository: [Microsoft/Web-Dev-For-Beginners](https://github.com/microsoft/Web-Dev-For-Beginners)
- Tags: how-to-guide
- Published: 2026-02-27

---

**Browser extensions use the standard Web Storage API (`localStorage`) to persist simple key-value data across sessions, with each extension page accessing a shared origin-scoped store at `chrome-extension://<extension-id>`.**

The `localStorage` API provides a straightforward mechanism for storing configuration data in browser extensions. In the **microsoft/Web-Dev-For-Beginners** repository, the browser extension solution demonstrates production-ready patterns for reading, writing, and clearing persistent data within the constraints of the Chrome Extension Manifest V3 architecture.

## Understanding localStorage Scope in Browser Extensions

Every HTML page within a browser extension—whether a popup, options page, or sidebar—runs in an isolated **origin** formatted as `chrome-extension://<extension-id>`. The `localStorage` object is automatically scoped to this origin, meaning data saved from one extension page is immediately available to all other pages of the same extension.

However, **Manifest V3 service workers** (background scripts) cannot access `localStorage` because they do not run in a document context. As implemented in [`5-browser-extension/solution/dist/background.js`](https://github.com/microsoft/Web-Dev-For-Beginners/blob/main/5-browser-extension/solution/dist/background.js), the background script must receive data via `chrome.runtime.sendMessage` from UI pages that handle the actual storage operations.

## Reading and Writing Data with localStorage

The Web Storage API provides synchronous methods for persistent data management. In [`5-browser-extension/solution/src/index.js`](https://github.com/microsoft/Web-Dev-For-Beginners/blob/main/5-browser-extension/solution/src/index.js), the extension follows a clear pattern for configuration persistence.

### Storing Configuration Data

When a user submits the setup form, the script captures input values and persists them using `localStorage.setItem()`:

```javascript
function saveUserSettings(apiKey, region) {
  // Store values for future sessions
  localStorage.setItem('apiKey', apiKey);
  localStorage.setItem('region', region);
}

// Hook into the extension UI
document.querySelector('.form-data').addEventListener('submit', e => {
  e.preventDefault();
  const apiKey = document.querySelector('.api-key').value;
  const region = document.querySelector('.region-name').value;
  saveUserSettings(apiKey, region);
  displayCarbonUsage(apiKey, region);
});

```

### Retrieving Saved Values

On initialization, the extension checks for existing configuration using `localStorage.getItem()` to determine whether to show the setup form or proceed with data fetching:

```javascript
function loadUserSettings() {
  const storedApiKey = localStorage.getItem('apiKey');
  const storedRegion = localStorage.getItem('region');

  if (storedApiKey && storedRegion) {
    // Previous configuration exists – use it immediately
    displayCarbonUsage(storedApiKey, storedRegion);
  } else {
    // No saved data – display configuration UI
    showSetupForm();
  }
}

// Run on extension popup load
loadUserSettings();

```

### Removing and Clearing Data

The reset functionality demonstrates selective deletion using `localStorage.removeItem()`, preserving the API key while clearing the region:

```javascript
function resetRegion() {
  // Remove only the region, retain API key for convenience
  localStorage.removeItem('region');
  // Or clear everything: localStorage.clear();
  loadUserSettings(); // Re-run initialization flow
}

document.querySelector('.clear-btn').addEventListener('click', resetRegion);

```

## Key Considerations for Extension Storage

When implementing `localStorage` in browser extensions, account for these technical constraints:

- **Persistence**: Data survives browser restarts and is sandboxed exclusively to the extension's origin.
- **Quota**: Approximately 5 MB per origin, sufficient for configuration strings but inadequate for large datasets.
- **Security**: `localStorage` stores data unencrypted in plain text; never persist sensitive secrets like passwords or private keys.
- **Synchronization**: Data does not automatically sync across devices. For cross-device persistence, use `chrome.storage.sync` instead.
- **Service Worker Limitations**: Background scripts cannot access `localStorage`; they must communicate with UI pages via message passing to retrieve stored values.

## Summary

- Browser extensions access `localStorage` through the standard Web Storage API, with data scoped to the extension's unique `chrome-extension://` origin.
- The **microsoft/Web-Dev-For-Beginners** extension demonstrates the complete workflow in [`5-browser-extension/solution/src/index.js`](https://github.com/microsoft/Web-Dev-For-Beginners/blob/main/5-browser-extension/solution/src/index.js): writing configuration with `setItem()`, reading with `getItem()`, and clearing with `removeItem()`.
- Manifest V3 service workers cannot directly access `localStorage`; UI pages must handle storage operations and communicate changes to the background script via `chrome.runtime.sendMessage`.
- Use `localStorage` for simple, non-sensitive configuration data under 5 MB, but prefer `chrome.storage.sync` for cross-device synchronization or `chrome.storage.local` for larger data needs.

## Frequently Asked Questions

### Can a Chrome extension background script use localStorage?

No. In Manifest V3, background scripts run as service workers without access to the DOM or `window` object, which means `localStorage` is unavailable. The background script must receive data from UI pages (popups or options pages) through `chrome.runtime.sendMessage` or use the `chrome.storage` API instead.

### How much data can I store in localStorage within a browser extension?

Browser extensions are limited to approximately **5 MB** of storage per origin (the `chrome-extension://<extension-id>` URL). This quota is shared across all pages of the extension. For configuration strings and small JSON objects this is sufficient, but for larger datasets you should use `chrome.storage.local`, which offers significantly more space (up to the browser's limit, typically hundreds of megabytes).

### Does localStorage data sync across devices when using the same Chrome extension?

No, `localStorage` is strictly local to the specific browser installation and does not synchronize across devices, even when the user is signed into Chrome with sync enabled. If you need cross-device persistence for extension settings, use **`chrome.storage.sync`** instead, which automatically synchronizes data across all signed-in instances of the browser.

### Is data stored in localStorage encrypted or secure?

Data stored in `localStorage` is **not encrypted**; it persists as plain text on the user's file system within the browser's profile directory. While the browser's sandboxing prevents other websites from accessing extension storage, any process with access to the file system can read these values. Therefore, never store sensitive information such as passwords, private API keys that require secrecy, or personal identification data in `localStorage`. Use the `chrome.storage` API with appropriate encryption or the browser's secure credential management for sensitive data.