Local Storage

Store data that persists even after the browser closes. Simple key-value storage.

Basics

Simple key-value storage that persists across sessions.

// Store data:
localStorage.setItem("username", "Alice");
localStorage.setItem("theme", "dark");

// Read data:
localStorage.getItem("username"); // "Alice"
localStorage.getItem("theme");    // "dark"
localStorage.getItem("missing");  // null (not undefined!)

// Remove one item:
localStorage.removeItem("theme");

// Clear everything:
localStorage.clear();

// Count items:
localStorage.length; // number of stored items

// Get key by index:
localStorage.key(0); // first key name

Persists

Survives page reload

Survives browser close

No expiration

Strings only

All values are strings

Must JSON.stringify objects

~5MB per origin

Storing Objects

localStorage only stores strings — use JSON for complex data.

// ❌ This doesn't work:
localStorage.setItem("user", { name: "Alice" });
localStorage.getItem("user"); // "[object Object]" 😬

// ✓ Use JSON:
const user = { name: "Alice", age: 25 };
localStorage.setItem("user", JSON.stringify(user));

const stored = localStorage.getItem("user");
const parsed = JSON.parse(stored);
parsed.name; // "Alice"

localStorage coerces everything to strings. JSON.stringify/parse lets you store any serializable data.

1 / 2

Practical Patterns

Common use cases for localStorage.

// 1. Remember user preferences:
function setTheme(theme) {
  document.documentElement.className = theme;
  localStorage.setItem("theme", theme);
}
// On page load:
const saved = localStorage.getItem("theme") || "light";
setTheme(saved);

// 2. Cache API responses:
async function fetchWithCache(url, ttlMs = 60000) {
  const cacheKey = `cache:${url}`;
  const cached = localStorage.getItem(cacheKey);
  
  if (cached) {
    const { data, timestamp } = JSON.parse(cached);
    if (Date.now() - timestamp < ttlMs) return data;
  }
  
  const res = await fetch(url);
  const data = await res.json();
  localStorage.setItem(cacheKey, JSON.stringify({
    data, timestamp: Date.now()
  }));
  return data;
}
// 3. Save form draft (auto-save):
const form = document.querySelector("form");
const DRAFT_KEY = "form-draft";

// Save on every input:
form.addEventListener("input", () => {
  const data = Object.fromEntries(new FormData(form));
  localStorage.setItem(DRAFT_KEY, JSON.stringify(data));
});

// Restore on page load:
const draft = localStorage.getItem(DRAFT_KEY);
if (draft) {
  const data = JSON.parse(draft);
  Object.entries(data).forEach(([key, value]) => {
    const field = form.elements[key];
    if (field) field.value = value;
  });
}

// Clear on submit:
form.addEventListener("submit", () => {
  localStorage.removeItem(DRAFT_KEY);
});

Limitations

What localStorage can't do.

Don't store:

  • • Passwords, tokens, or sensitive data (accessible via JS = XSS risk)
  • • Large datasets (>5MB throws QuotaExceededError)
  • • Data that must be real-time synced (no reactivity)
  • • Non-serializable data (functions, DOM elements, circular refs)
// Synchronous = blocks the main thread:
// Avoid reading/writing large data in hot paths

// Can be cleared by user:
// Users can clear site data at any time
// Always have a fallback for missing data

// Same-origin only:
// https://example.com can't read from https://other.com
// http:// and https:// are different origins!

// Private/incognito:
// Some browsers limit or clear storage in private mode
// Safari: 7-day cap on storage without user interaction

Storage Events

Detect changes made in OTHER tabs.

// Fires when localStorage changes in ANOTHER tab:
window.addEventListener("storage", (e) => {
  e.key;        // which key changed
  e.oldValue;   // previous value (string)
  e.newValue;   // new value (string, null if removed)
  e.url;        // URL of page that made the change
  e.storageArea; // localStorage or sessionStorage
  
  // Sync theme across tabs:
  if (e.key === "theme") {
    document.documentElement.className = e.newValue;
  }
});

// ⚠️ Does NOT fire in the tab that made the change!
// Only fires in other same-origin tabs/windows.

// Use case: logout from all tabs:
// Tab 1 sets: localStorage.removeItem("token")
// Tab 2 detects removal → redirects to login

FAQ

Common questions about localStorage.