LocalStorage & SessionStorage Get Certified
The Web Storage API gives you two simple key-value stores that
live in the browser: localStorage and
sessionStorage. Both use the same methods, but they
differ in how long the data lasts and whether it is shared across
tabs.
Basic Usage: setItem, getItem, removeItem
The core methods are the same for both storage objects. Because this tutorial runs in a sandbox, the examples below use a small mock that behaves like the real Web Storage API.
What this code does: Demonstrates the three fundamental methods — storing a value, reading it back, and removing it.
function createMockStorage() {
const data = {};
return {
setItem(key, value) {
data[key] = String(value);
},
getItem(key) {
return Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
},
removeItem(key) {
delete data[key];
}
};
}
const mockLocalStorage = createMockStorage();
mockLocalStorage.setItem("username", "Michael");
console.log(mockLocalStorage.getItem("username"));
mockLocalStorage.removeItem("username");
console.log(mockLocalStorage.getItem("username"));
String(value) — real storage also coerces everything to a string.null if the key was never set (does not throw).localStorage."username"."Michael".null.getItem Returns null for Missing Keys
If a key has never been set (or has been removed),
getItem() returns null instead of
throwing an error.
What this code does: Shows that reading a key
that does not exist safely returns null.
function createMockStorage() {
const data = {};
return {
setItem(key, value) {
data[key] = String(value);
},
getItem(key) {
return Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
}
};
}
const mockLocalStorage = createMockStorage();
console.log(mockLocalStorage.getItem("nonexistent"));
console.log(mockLocalStorage.getItem("nonexistent") === null);
getItem returns null — it never throws for a missing key.null before using the result, or you risk errors later.clear() and the length Property
clear() removes every key at once.
The length property tells you how many keys are
currently stored.
What this code does: Stores a few items, checks the length, then clears everything and checks the length again.
function createMockStorage() {
const data = {};
return {
setItem(key, value) {
data[key] = String(value);
},
getItem(key) {
return Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
},
clear() {
Object.keys(data).forEach(key => delete data[key]);
},
get length() {
return Object.keys(data).length;
}
};
}
const mockLocalStorage = createMockStorage();
mockLocalStorage.setItem("username", "Michael");
mockLocalStorage.setItem("theme", "dark");
console.log("Before clear:", mockLocalStorage.length);
mockLocalStorage.clear();
console.log("After clear:", mockLocalStorage.length);
Storing Objects with JSON
Web Storage can only hold strings. To store an object or array,
convert it with JSON.stringify() first, and convert
it back with JSON.parse() when reading it.
What this code does: Stores a complex object by
converting it with JSON.stringify and reading it
back with JSON.parse.
function createMockStorage() {
const data = {};
return {
setItem(key, value) {
data[key] = String(value);
},
getItem(key) {
return Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
}
};
}
const mockLocalStorage = createMockStorage();
const user = { name: "Michael", age: 28 };
mockLocalStorage.setItem("user", JSON.stringify(user));
const storedUser = JSON.parse(mockLocalStorage.getItem("user"));
console.log(storedUser.name);
console.log(storedUser.age);
name and age work normally.Everything Is Stored as a String
Even numbers and booleans are converted to strings when stored. You must convert them back to the correct type yourself when reading them.
What this code does: Highlights that Web Storage only holds strings — numbers and booleans are coerced when saved.
function createMockStorage() {
const data = {};
return {
setItem(key, value) {
data[key] = String(value);
},
getItem(key) {
return Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
}
};
}
const mockLocalStorage = createMockStorage();
mockLocalStorage.setItem("count", 5);
const value = mockLocalStorage.getItem("count");
console.log(typeof value); // "string"
console.log(value + 1); // "51" (concatenation)
console.log(Number(value) + 1); // 6
"5"."string" — this surprises many beginners."5" + 1 concatenates → "51", not 6.Number(value) (or parseInt) before math.
Notice that value + 1 produces "51"
(string concatenation), while Number(value) + 1
correctly produces 6.
Iterating Over All Stored Keys
The length property and key(index)
method let you loop through every stored key without knowing
their names in advance.
What this code does: Iterates over every stored
key using the length property and
key(index) method.
function createMockStorage() {
const data = {};
return {
setItem(key, value) {
data[key] = String(value);
},
getItem(key) {
return Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
},
key(index) {
return Object.keys(data)[index] || null;
},
get length() {
return Object.keys(data).length;
}
};
}
const mockLocalStorage = createMockStorage();
mockLocalStorage.setItem("username", "Michael");
mockLocalStorage.setItem("theme", "dark");
mockLocalStorage.setItem("language", "en");
for (let i = 0; i < mockLocalStorage.length; i++) {
const key = mockLocalStorage.key(i);
console.log(key + " = " + mockLocalStorage.getItem(key));
}
null if out of range.key(i) gives the name at position i.getItem(key) reads the value for that name.localStorage vs. sessionStorage
Both objects share the exact same interface — the difference is
how long the data lasts. sessionStorage is scoped
to a single tab and is cleared when that tab is closed;
localStorage persists until it is explicitly
removed, even after the browser is closed and reopened.
What this code does: Contrasts
localStorage (persists across sessions) with
sessionStorage (cleared when the tab closes).
function createMockStorage() {
const data = {};
return {
setItem(key, value) {
data[key] = String(value);
},
getItem(key) {
return Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
}
};
}
const mockLocalStorage = createMockStorage();
const mockSessionStorage = createMockStorage();
mockLocalStorage.setItem("shared", "Stays after the browser restarts");
mockSessionStorage.setItem("shared", "Gone when this tab closes");
console.log("localStorage:", mockLocalStorage.getItem("shared"));
console.log("sessionStorage:", mockSessionStorage.getItem("shared"));
The storage Event
On a real page, whenever localStorage changes in
one tab, the browser fires a storage event in
every other open tab from the same origin (not
the tab that made the change). This is commonly used to keep
multiple open tabs in sync, such as logging every tab out at
once. This behavior needs multiple real browser tabs to observe
and cannot be demonstrated inside this single-page sandbox.
localStorage vs sessionStorage
| Feature | localStorage | sessionStorage |
|---|---|---|
| Persists after the browser closes? | Yes | No |
| Shared across tabs of the same origin? | Yes | No — separate per tab |
| Cleared automatically when? | Only when explicitly removed | When the tab is closed |
| Same interface (setItem, getItem, etc.)? | Yes | Yes |
| Typical use case | User preferences, saved settings | Temporary form data, one-time flags |
Common Mistakes with Web Storage
- Storing an object or array without
JSON.stringify(), which silently stores the unhelpful string"[object Object]". - Forgetting to convert a stored number or boolean back to its real type after reading it as a string.
- Storing sensitive data (passwords, tokens) in
localStorage, which is readable by any script running on the page. - Assuming
sessionStorageis shared between tabs — it is not, even for tabs on the same site. - Not handling the case where
getItem()returnsnullfor a key that was never set.
What this code does: Demonstrates the classic
mistake of storing an object without
JSON.stringify().
function createMockStorage() {
const data = {};
return {
setItem(key, value) {
data[key] = String(value);
},
getItem(key) {
return Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
}
};
}
const mockLocalStorage = createMockStorage();
const user = { name: "Michael" };
// Mistake: forgetting JSON.stringify()
mockLocalStorage.setItem("user", user);
console.log(mockLocalStorage.getItem("user")); // "[object Object]"
String().JSON.stringify → String(obj) becomes the useless "[object Object]".Best Practices for Web Storage
- Always use
JSON.stringify()andJSON.parse()when storing or reading objects and arrays. - Never store sensitive information like passwords or authentication tokens in
localStorage. - Check for
nullwhen reading a key that may not exist yet. - Use
sessionStoragefor short-lived, per-tab data, andlocalStoragefor data that should persist across visits. - Wrap storage operations in
try...catchin production code, since storage can throw if it is full or disabled by the browser.
Quick Summary
setItem(),getItem(),removeItem(), andclear()are the core methods shared by both storage objects.getItem()returnsnullfor a missing key instead of throwing an error.- Everything is stored as a string — use
JSON.stringify()/JSON.parse()for objects and arrays, and convert numbers manually. lengthandkey(index)let you loop through all stored keys.localStoragepersists indefinitely;sessionStorageis cleared when the tab closes and is not shared between tabs.- A
storageevent fires in other open tabs whenlocalStoragechanges.
Try It Yourself
Modify the code below. Try storing a different object, removing
one key while keeping another, or checking what
getItem() returns after calling
clear().
What this code does: A practice exercise that stores settings as JSON, reads them back, removes a key, and inspects the remaining data.
function createMockStorage() {
const data = {};
return {
setItem(key, value) {
data[key] = String(value);
},
getItem(key) {
return Object.prototype.hasOwnProperty.call(data, key) ? data[key] : null;
},
removeItem(key) {
delete data[key];
},
clear() {
Object.keys(data).forEach(key => delete data[key]);
},
get length() {
return Object.keys(data).length;
}
};
}
const mockLocalStorage = createMockStorage();
const settings = { theme: "dark", fontSize: 16 };
mockLocalStorage.setItem("settings", JSON.stringify(settings));
mockLocalStorage.setItem("username", "Michael");
console.log("Total keys:", mockLocalStorage.length);
const savedSettings = JSON.parse(mockLocalStorage.getItem("settings"));
console.log("Theme:", savedSettings.theme);
mockLocalStorage.removeItem("username");
console.log("Username after removal:", mockLocalStorage.getItem("username"));
null. Try clear() next to wipe everything.Tip: Treat Web Storage as a plain string-only key-value store — alwaysJSON.stringify()objects going in andJSON.parse()them coming out, and reach forsessionStorageinstead oflocalStoragewhenever the data truly only needs to last for one tab.
Understanding localStorage and
sessionStorage gives you a simple way to persist
data on the client side, and pairs naturally with the Fetch API
for caching data retrieved from a server.
🧪 Test Your JavaScript Code
Edit the code on the left and click "Run Code" to see the console output on the right.
Click "Run Code" to see the output here.
Code Explanation
The complete example stays visible. Use Previous and Next to move through its logical blocks.
Select Next to begin exploring the code.