JavaScript course menu
localStorage and sessionStorage in JavaScript: Saving Data in the Browser
Learn the Web Storage API: saving, reading and removing data with localStorage and sessionStorage, storing objects with JSON, the differences between localStorage, sessionStorage and cookies, storage limits, the storage event, and what not to store.
On this page
Normally everything in a web page is lost when it is reloaded. The Web Storage API gives each website a small key-value store in the browser that survives reloads: perfect for theme choices, drafts, a shopping cart before checkout, or a to-do list.
Saving and reading#
localStorage.setItem("theme", "dark");
const theme = localStorage.getItem("theme");
console.log(theme); // "dark"
console.log(localStorage.getItem("missing")); // null
localStorage.removeItem("theme");
localStorage.clear(); // remove everything for this siteOnly strings#
Web Storage stores strings only. Numbers become strings, and objects become the useless string "[object Object]":
localStorage.setItem("count", 5);
console.log(typeof localStorage.getItem("count")); // "string"
localStorage.setItem("user", { name: "Asha" });
console.log(localStorage.getItem("user")); // "[object Object]"Use JSON to store objects and arrays:
const cart = [{ id: 1, qty: 2 }, { id: 7, qty: 1 }];
localStorage.setItem("cart", JSON.stringify(cart));
const saved = JSON.parse(localStorage.getItem("cart") ?? "[]");
console.log(saved.length); // 2?? "[]" provides a default when nothing has been saved yet.
A safe helper#
Stored data can be missing, corrupted, or blocked (some browsers block storage in private modes or when the user disables site data). Wrap access in try...catch:
function load(key, fallback) {
try {
const raw = localStorage.getItem(key);
return raw === null ? fallback : JSON.parse(raw);
} catch {
return fallback;
}
}
function save(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch {
// storage is full or unavailable: the app keeps working without saving
}
}A to-do list that survives reloads#
Save this as an HTML file and open it in your browser. Add some items, reload the page, and they are still there:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>Saved to-do list</title></head>
<body>
<form id="form"><input id="task" placeholder="New task" required> <button>Add</button></form>
<ul id="list"></ul>
<script>
const list = document.querySelector("#list");
const input = document.querySelector("#task");
let tasks = JSON.parse(localStorage.getItem("tasks") ?? "[]");
function render() {
list.replaceChildren(...tasks.map((text) => {
const li = document.createElement("li");
li.textContent = text;
return li;
}));
}
document.querySelector("#form").addEventListener("submit", (event) => {
event.preventDefault();
tasks.push(input.value.trim());
localStorage.setItem("tasks", JSON.stringify(tasks));
input.value = "";
render();
});
render();
</script>
</body>
</html>The pattern is: load the saved data on start, render it, and save again after every change.
localStorage, sessionStorage or cookies?#
sessionStorage has exactly the same methods as localStorage; only its lifetime differs. Use it for temporary state such as a multi-step form in one tab.
Storage is separate for each origin (scheme, domain and port), so one website cannot read another's data.
Listening for changes from other tabs#
When one tab changes localStorage, other open tabs of the same site receive a storage event, which you can use to keep them in sync:
window.addEventListener("storage", (event) => {
if (event.key === "theme") applyTheme(event.newValue);
});What not to store#
- Secrets and sensitive data: passwords, card numbers, personal information. Any script running on the page, including a malicious one injected through an XSS bug, can read
localStorage. - Authentication tokens: many teams prefer
HttpOnlycookies, which JavaScript cannot read. - Large data: storage is small and synchronous (it blocks the page while reading and writing). For large or structured data, browsers provide IndexedDB.
Practice#
Practice exercise
Write two functions, saveSettings(settings) and loadSettings(), that store an object like { theme: "dark", fontSize: 18 } under the key "settings", and that return { theme: "light", fontSize: 16 } when nothing is saved or the saved data is broken.
Show solution
const DEFAULT_SETTINGS = { theme: "light", fontSize: 16 };
function saveSettings(settings) {
try {
localStorage.setItem("settings", JSON.stringify(settings));
} catch {
// ignore: settings just will not be remembered
}
}
function loadSettings() {
try {
const raw = localStorage.getItem("settings");
return raw ? { ...DEFAULT_SETTINGS, ...JSON.parse(raw) } : { ...DEFAULT_SETTINGS };
} catch {
return { ...DEFAULT_SETTINGS };
}
}Spreading the defaults first means a saved object missing a newer setting still gets its default value.
Key takeaway#
Finished this lesson?