Skip to main content

Web Storage

What is web storage?

Web storage lets your JavaScript save small amounts of data in the browser. The two main APIs are localStorage and sessionStorage.

Smallest working example

localStorage.setItem("theme", "dark");

const theme = localStorage.getItem("theme");
console.log(theme); // "dark"

Why this matters

Web storage is useful when your page needs to remember something:

  • User preferences like theme or language
  • Draft form values
  • Small pieces of UI state
  • Data that should survive a refresh

localStorage

localStorage stores data that stays available after the browser is closed and reopened.

Basic usage

localStorage.setItem("username", "Alice");
localStorage.setItem("theme", "dark");

const username = localStorage.getItem("username");
console.log(username); // "Alice"

localStorage.removeItem("username");
localStorage.clear();

Storing objects

localStorage only stores strings, so objects need JSON:

const user = {
name: "Alice",
email: "alice@example.com",
preferences: {
theme: "dark"
}
};

localStorage.setItem("user", JSON.stringify(user));

const rawUser = localStorage.getItem("user");
if (rawUser) {
const savedUser = JSON.parse(rawUser);
console.log(savedUser.name);
}

Checking whether a key exists

const username = localStorage.getItem("username");

if (username !== null) {
console.log("Username:", username);
} else {
console.log("No username stored");
}

sessionStorage

sessionStorage uses the same API as localStorage, but its data lasts only for the current browser tab session.

sessionStorage.setItem("tempData", "value");

const data = sessionStorage.getItem("tempData");
console.log(data);

sessionStorage.removeItem("tempData");

Choosing the right storage

  • Use localStorage when the data should still be there after the browser closes
  • Use sessionStorage when the data should belong only to the current tab session
  • Use plain JavaScript variables when the data only needs to exist while the page is open
  • Use IndexedDB when the data is larger, more structured, or more complex than simple key-value storage
tip

Rule of thumb: if you only need to store a few strings or small JSON objects, localStorage is often enough. If you start storing lots of records or more complex app data, Web Storage is probably the wrong tool.

When storage is appropriate

Good fits for Web Storage:

  • User preferences
  • Draft form data
  • Small persisted app state
  • Shopping cart state for simple apps

Poor fits for Web Storage:

  • Large datasets
  • Sensitive information like passwords
  • Frequently changing high-volume data
  • Complex relational or offline-first application data

Persisting application state

function saveState(todos, currentTheme) {
const state = {
items: todos.items,
filter: todos.filter,
theme: currentTheme
};

localStorage.setItem("appState", JSON.stringify(state));
}

function loadState() {
const saved = localStorage.getItem("appState");
if (!saved) {
return null;
}

return JSON.parse(saved);
}

Example: save a form draft

const form = document.querySelector("#contact-form");

if (form) {
form.addEventListener("input", () => {
const formData = new FormData(form);
const data = Object.fromEntries(formData);
localStorage.setItem("formDraft", JSON.stringify(data));
});

const draft = localStorage.getItem("formDraft");
if (draft) {
const data = JSON.parse(draft);

Object.keys(data).forEach(key => {
const input = form.querySelector(`[name="${key}"]`);
if (input) {
input.value = data[key];
}
});
}

form.addEventListener("submit", () => {
localStorage.removeItem("formDraft");
});
}

Storage events

The browser can tell other tabs when storage changed:

window.addEventListener("storage", event => {
console.log("Storage changed:", event.key);
console.log("Old value:", event.oldValue);
console.log("New value:", event.newValue);
});
note

The storage event fires in other tabs or windows, not in the same tab that made the change.

Limitations and errors

Size limits

Web Storage is intentionally small:

  • localStorage / sessionStorage are usually around 5-10 MB per origin
  • Limits vary by browser
  • Going over the limit throws a QuotaExceededError

Handling storage failures

try {
localStorage.setItem("largeData", largeString);
} catch (error) {
if (error.name === "QuotaExceededError") {
console.error("Storage quota exceeded");
}
}

Checking availability

Some environments or privacy modes may restrict storage:

function isStorageAvailable() {
try {
localStorage.setItem("test", "test");
localStorage.removeItem("test");
return true;
} catch (error) {
return false;
}
}

Best practices

Wrap storage access in helpers

const storage = {
set(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
return true;
} catch (error) {
console.error("Storage error:", error);
return false;
}
},

get(key) {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : null;
} catch (error) {
console.error("Storage error:", error);
return null;
}
},

remove(key) {
localStorage.removeItem(key);
}
};

Do not store sensitive data

// Bad
localStorage.setItem("password", password);
// Better
localStorage.setItem("username", username);

Expect stale or missing data

const settings = storage.get("settings");

if (settings) {
applySettings(settings);
} else {
applyDefaultSettings();
}

Summary

  • Web Storage gives you simple browser-side key-value storage.
  • Use localStorage for data that should survive browser restarts and sessionStorage for tab-scoped data.
  • Store objects as JSON strings and parse them when reading.
  • Web Storage is best for small, simple data, not large or sensitive information.

Next up