Refresh the page and every variable is gone. localStorage lets you save small amounts of data in the browser so it's still there next time: a visitor's chosen theme, a draft message, a to-do list or a game's high score. No server or database is needed.
localStorage is one of the simplest ways to make a small app feel complete. A to-do list that forgets everything on refresh feels like a demo; one that remembers its items feels like a real tool. This lesson shows how to save and load data safely, including arrays and objects.
The four localStorage methods
localStorage.setItem("theme", "dark"); // save
localStorage.getItem("theme"); // "dark" (or null if missing)
localStorage.removeItem("theme"); // delete one item
localStorage.clear(); // delete everything for this siteData is stored as pairs of string keys and string values. Each website gets its own separate storage, and the data has no expiry date. It stays until your code or the visitor removes it.
Storing arrays and objects with JSON
localStorage only stores strings. Convert arrays and objects with JSON:
localStorage.setItem("todos", JSON.stringify(todos));
const todos = JSON.parse(localStorage.getItem("todos")) ?? [];The ?? [] provides a sensible default the first time the page loads, when nothing has been saved yet.
If you store a number, it comes back as a string, so "5" needs converting with Number() before you do maths with it.
sessionStorage
sessionStorage has exactly the same methods, but its data disappears when the tab is closed. It's useful for temporary information, such as the progress of a half-finished form in one tab.
Limits and safety
- Each site gets roughly 5MB of storage.
- Visitors can see and edit the data in DevTools (in the Application tab), so never store passwords or other secrets there.
- Storage can be unavailable, for example in some private browsing modes, so wrap it in
try...catchin real apps. - Saving and loading is synchronous, so keep the amount of data small to avoid slowing the page down.
localStorage vs other storage options
| Option | Lasts | Size | Good for |
|---|---|---|---|
localStorage | Until cleared | About 5 MB | Preferences, drafts, small saved lists |
sessionStorage | Until the tab closes | About 5 MB | A multi-step form in one tab |
| Cookies | Set expiry date | About 4 KB | Data the server must read on every request |
| IndexedDB | Until cleared | Hundreds of MB | Large data, offline apps, files |
All of them belong to one site only: a page on another domain can't read your localStorage. But any script running on your page can, including third-party scripts, so never store passwords, payment details or private tokens there. The storage event fires in your other open tabs when a value changes, which lets several tabs stay in sync.
localStorage Syntax
localStorage
localStorage.setItem("key", "value");
const value = localStorage.getItem("key");
localStorage.setItem("list", JSON.stringify([1, 2]));
const list = JSON.parse(localStorage.getItem("list")) ?? [];localStorage Summary
- localStorage saves string data in the browser between visits.
- Use
setItem,getItem,removeItemandclearto manage it. - Convert arrays and objects with
JSON.stringifyandJSON.parse. sessionStorageworks the same way but clears when the tab closes.- Never store secrets in localStorage, and handle the case where it's unavailable.
localStorage Examples
Each example runs in the page. Edit the code and press Run to see what changes.
Saving a preference
Pick a colour, then press Run again. Your choice is remembered. (Previews on this site use a safe in-memory stand-in for storage.)
<label>Favourite colour <input type="color" id="fav"></label>
<p id="msg"></p>const picker = document.querySelector("#fav");
const msg = document.querySelector("#msg");
const saved = localStorage.getItem("favColor") ?? "#17a865";
picker.value = saved;
msg.textContent = `Saved colour: ${saved}`;
picker.addEventListener("input", () => {
localStorage.setItem("favColor", picker.value);
msg.textContent = `Saved colour: ${picker.value}`;
});Line-by-line explanation
- Line 4Load the saved value, or a default the first time.
- Lines 8 to 11Save whenever the user picks a new colour.
Storing an array with JSON
const key = "visits";
const visits = JSON.parse(localStorage.getItem(key)) ?? [];
visits.push(new Date().toLocaleTimeString());
localStorage.setItem(key, JSON.stringify(visits));
console.log(`You've run this ${visits.length} time(s):`);
console.log(visits);Line-by-line explanation
- Line 3Read the saved array (or start empty).
- Line 4Add the current time.
- Line 5Save the whole array back as a JSON string.
A to-do list that survives refresh
<form id="add"><input id="task" placeholder="New task" required> <button>Add</button></form>
<ul id="list"></ul>
<button id="clear">Clear all</button>const form = document.querySelector("#add");
const input = document.querySelector("#task");
const list = document.querySelector("#list");
let tasks = JSON.parse(localStorage.getItem("tasks")) ?? [];
function render() {
list.replaceChildren();
for (const t of tasks) {
const li = document.createElement("li");
li.textContent = t;
list.append(li);
}
}
function save() {
localStorage.setItem("tasks", JSON.stringify(tasks));
}
form.addEventListener("submit", (e) => {
e.preventDefault();
tasks.push(input.value.trim());
input.value = "";
save();
render();
});
document.querySelector("#clear").addEventListener("click", () => {
tasks = [];
save();
render();
});
render();Line-by-line explanation
- Line 5Load saved tasks once at the start.
- Lines 7 to 14One function draws the list from the data.
- Lines 16 to 18One function saves the data.
- Lines 20 to 26On submit: update data → save → re-render.
Common localStorage Mistakes
Storing objects without JSON
localStorage.setItem("user", { name: "Ali" });
localStorage.getItem("user"); // "[object Object]"localStorage.setItem("user", JSON.stringify({ name: "Ali" }));
JSON.parse(localStorage.getItem("user")); // { name: "Ali" }Forgetting numbers come back as strings
const score = localStorage.getItem("score"); // "10"
score + 5; // "105"const score = Number(localStorage.getItem("score") ?? 0);
score + 5; // 15localStorage in Real Projects
Where localStorage is used
Theme and language preferences, "remember my cart" on shops, draft emails, onboarding tips you've dismissed, offline note apps and browser games' save slots. For large or private data, apps use IndexedDB or a server instead.
localStorage Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Save and then read the user's name.
localStorage.("username", "Ola");
const name = localStorage.("username");
What does localStorage.getItem("missing") return?
How do you store an array in localStorage?
The high score should be saved as a number and doubled to log Double: 84. Fix the reading code.
localStorage.setItem("high", JSON.stringify(42));
const high = localStorage.getItem("high");
console.log("Double:", high + high);- Logs "Double: 84"
localStorage Quiz
3 questions to check what you learned.
Does localStorage data survive a page refresh?
- No
- Only for 1 hour
- Yes
- Only in Chrome
What's the difference between localStorage and sessionStorage?
- sessionStorage is cleared when the tab closes
- sessionStorage is bigger
- localStorage is server-side
- No difference
Should you store passwords in localStorage?
- No. It's readable by any script on the page and in DevTools
- Yes, it's encrypted
- Only short ones
- Only in sessionStorage
localStorage Challenge
Remember the click count
Make a counter that survives refresh:
- Read
clicksfrom localStorage (default0) and show it in#n - On each click of
#btn, add 1, save it, and update#n
<button id="btn">Click me</button>
<p>Total clicks: <span id="n">0</span></p>const btn = document.querySelector("#btn");
const n = document.querySelector("#n");
- Clicking updates the display
- The count is saved