</> HTML5Advent
ENFRESDEITPT

// apis · Web Platform Advent #6

localStorage vs sessionStorage: the Web Storage API explained

When to use localStorage vs sessionStorage — how they differ in lifetime and scope, their size limits, how to store JSON safely, and reacting to the storage event.

A narrow archive aisle lined with shelves of labelled storage boxes and binders

The Web Storage API gives the browser two simple key-value stores — localStorage and sessionStorage — for keeping small amounts of data on the user's device. Both share the exact same API; they differ only in how long the data lives and who can see it.

The shared API

Both objects expose the same five methods, and both store strings only:

localStorage.setItem('theme', 'dark');
const theme = localStorage.getItem('theme'); // 'dark'
localStorage.removeItem('theme');
localStorage.clear();                          // wipe everything
console.log(localStorage.length);              // number of keys

Reading a key that does not exist returns null, so you can fall back with ||:

const theme = localStorage.getItem('theme') || 'light';

The one real difference: lifetime

This is the whole decision in one sentence. localStorage persists until you delete it — it survives reloads, tab closes and browser restarts. sessionStorage lives only as long as the tab does: close the tab and the data is gone, and a second tab on the same site gets its own separate store.

A screen showing colourful JavaScript source code that reads from the window object
Both stores hang off the global window object, so localStorage and window.localStorage refer to exactly the same thing.

Storing objects: stringify and parse

Because storage holds only strings, anything structured must go through JSON. Serialize on the way in, parse on the way out:

const user = { name: 'Ada', loggedIn: true };

// Save
localStorage.setItem('user', JSON.stringify(user));

// Read back
const saved = JSON.parse(localStorage.getItem('user'));
console.log(saved.name); // 'Ada'

Wrap JSON.parse in a try/catch when the value might be missing or corrupted — parsing null or invalid text throws:

function readJSON(key, fallback) {
  try {
    const raw = localStorage.getItem(key);
    return raw ? JSON.parse(raw) : fallback;
  } catch {
    return fallback;
  }
}

Scope and the size limit

Storage is scoped to the origin (scheme + host + port): https://example.com and http://example.com do not share data. The quota is roughly 5 MB per origin in most browsers — generous for preferences and small caches, but not a database. Exceeding it makes setItem throw a QuotaExceededError, so guard large writes.

Reacting to changes across tabs

The storage event fires on other tabs of the same origin when localStorage changes — handy for syncing a logout or a theme switch across open windows. Note it does not fire in the tab that made the change, and sessionStorage never triggers it:

window.addEventListener('storage', (event) => {
  if (event.key === 'theme') {
    applyTheme(event.newValue);
  }
});

Which one should you use?

localStoragesessionStorage
LifetimeUntil explicitly clearedUntil the tab closes
Shared between tabsYes (same origin)No (per tab)
Survives reloadYesYes
Fires storage eventYesNo
Typical useTheme, settings, "remember me"One-off form drafts, wizard steps

Reach for localStorage when the data should stick around between visits, and sessionStorage when it is meaningful only for the current tab. For anything sensitive — tokens, passwords, personal data — neither is appropriate: both are readable by any script on the page, so keep secrets out of Web Storage entirely.