SKU // 135

JS Web Storage

Web Storage lets a page keep small pieces of data in the visitor's own browser: a chosen theme, a half-written note, a game score. It works like a tiny object that survives page reloads, and it is far simpler than cookies. This lesson covers the two kinds of storage, the handful of methods, the strings-only rule that sends everything through JSON, and the limits to know about.

A note about the examples. Your code in the Try It editor runs on this site, so the storage it uses is the same storage this site uses for your themes, notes, and saved drafts. Every example here uses keys that start with demo_ and cleans up after itself. Never call localStorage.clear() here: it would erase your saved notes and settings for this whole site.

// Two Kinds of Storage

Storage Lasts Shared
localStoragestays until it is deleted: closing the browser or restarting the computer does not remove itevery tab and window of the same site share it
sessionStorageis erased when the tab is closedeach tab has its own, even for the same site

Both have exactly the same methods, so everything below works for either. Storage belongs to one origin (the protocol, host, and port): a page on one site can never read what another site stored.

// The Five Things You Can Do

Method or property Does
setItem(key, value)save a value (adds the key or replaces the old value)
getItem(key)read a value, or null if the key does not exist
removeItem(key)delete one key
key(index)the name of the key at a position
lengthhow many keys there are
localStorage.setItem("demo_name", "Ava");
console.log(localStorage.getItem("demo_name"));
console.log(localStorage.getItem("demo_missing"));

localStorage.removeItem("demo_name");
console.log(localStorage.getItem("demo_name"));
Ava null null

There is also a shorthand that treats storage like an object (localStorage.demo_name = "Ava"), but setItem and getItem are clearer and safer, so use them.

// Everything Is a String

Storage keeps only strings. Anything else is turned into text on the way in, and comes back as text:

localStorage.setItem("demo_count", 5);
const value = localStorage.getItem("demo_count");

console.log(typeof value);
console.log(value + 1);
console.log(Number(value) + 1);

localStorage.removeItem("demo_count");
string 51 6
Objects become [object Object]
Saving an object directly stores the useless text "[object Object]". Convert objects and arrays with JSON.stringify on the way in and JSON.parse on the way out.

// Saving Objects: JSON to the Rescue

const settings = { theme: "dark", fontSize: 18, tags: ["a", "b"] };

localStorage.setItem("demo_settings", JSON.stringify(settings));

const loaded = JSON.parse(localStorage.getItem("demo_settings"));
console.log(loaded.theme, loaded.fontSize + 2, loaded.tags.length);

localStorage.removeItem("demo_settings");
dark 20 2

// Two Small Helpers

Because getItem returns null for a missing key, and JSON.parse throws on bad text, it is worth wrapping the pattern once:

function save(key, value) {
  localStorage.setItem(key, JSON.stringify(value));
}

function load(key, fallback) {
  const text = localStorage.getItem(key);
  if (text === null) return fallback;
  try {
    return JSON.parse(text);
  } catch (error) {
    return fallback;
  }
}

console.log(load("demo_score", 0));
save("demo_score", 42);
console.log(load("demo_score", 0));

localStorage.setItem("demo_bad", "{oops");
console.log(load("demo_bad", "recovered"));

localStorage.removeItem("demo_score");
localStorage.removeItem("demo_bad");
0 42 recovered

// Listing What Is Stored

localStorage.length and localStorage.key(i) let you loop through every key. Because this site stores its own keys too, the example filters to the demo_ ones:

localStorage.setItem("demo_b", "2");
localStorage.setItem("demo_a", "1");

const mine = [];
for (let i = 0; i < localStorage.length; i++) {
  const key = localStorage.key(i);
  if (key.startsWith("demo_")) mine.push(key);
}
console.log(mine.sort());

localStorage.removeItem("demo_a");
localStorage.removeItem("demo_b");
["demo_a", "demo_b"]

// A Page That Remembers

Here a button counts clicks and the count survives a reload. Close the Result pane and run it again: the number is still there. The Reset button clears it:

<p>Clicks: <strong id="n">0</strong></p>
<button id="add">Click me</button>
<button id="reset">Reset</button>

<script>
  const n = document.getElementById("n");
  let count = Number(localStorage.getItem("demo_clicks")) || 0;
  n.textContent = count;

  document.getElementById("add").addEventListener("click", function () {
    count++;
    n.textContent = count;
    localStorage.setItem("demo_clicks", count);
  });

  document.getElementById("reset").addEventListener("click", function () {
    count = 0;
    n.textContent = 0;
    localStorage.removeItem("demo_clicks");
  });
</script>

// sessionStorage

sessionStorage is used the same way. The only difference is that the data disappears when the tab closes, which suits things like the step of a form the person is partway through:

sessionStorage.setItem("demo_step", "2");
console.log(sessionStorage.getItem("demo_step"));
console.log(localStorage.getItem("demo_step"));
sessionStorage.removeItem("demo_step");
2 null

// Limits and Cautions

// Storage Across Tabs: the storage Event

When one tab changes localStorage, every other tab of the same site gets a "storage" event, which lets tabs stay in sync (a theme change, a logout). The tab that made the change does not get it:

window.addEventListener("storage", function (event) {
  console.log(event.key, "changed from", event.oldValue, "to", event.newValue);
});

// Quick Check

What does this log?

localStorage.setItem("demo_n", 5);
console.log(typeof localStorage.getItem("demo_n"));
localStorage.removeItem("demo_n");
Show answer
string. Storage keeps only text, so the number 5 comes back as the string "5". Convert with Number(...) before doing math.

What does this log?

const user = { name: "Ava" };
localStorage.setItem("demo_u", user);
console.log(localStorage.getItem("demo_u"));
localStorage.removeItem("demo_u");
Show answer
[object Object]. An object is converted with String(...), which gives that useless text. Use JSON.stringify(user) when saving.

Name one difference between localStorage and cookies.

Show answer
Any of: localStorage is not sent to the server with each request, it holds much more data (about 5 MB versus 4 KB), it has a simpler API, and it does not expire on its own.

// Try It

  1. Click Open Playground and run it. Run it again: what changed?
  2. Save an array of three names with the helpers and load it back
  3. Make a note-taking box that saves its text as you type and shows it again after a reload
  4. Change the counter to use sessionStorage and explain the difference you see
// Video Walkthroughs
Last updated: Oct 11, 2026, 8:40 PM ET