LocalStorage and SessionStorage
localStorage and sessionStorage are key-value stores that survive page refreshes. Unlike cookies, theyβre not sent with HTTP requests β making them ideal for client-side data.
Web Storage API
Both share the same API:
// Set
localStorage.setItem('key', 'value');
// Get
const value = localStorage.getItem('key');
// Remove
localStorage.removeItem('key');
// Clear all
localStorage.clear();
// Get count
localStorage.length;
// Get key by index
localStorage.key(0);
localStorage vs sessionStorage
| Feature | localStorage | sessionStorage |
|---|---|---|
| Persists after browser close | β Yes | β No |
| Survives page refresh | β Yes | β Yes |
| Tab-isolated | β Shared across tabs | β Per-tab |
| Survives tab close | β Yes | β No |
| Capacity | ~5-10MB | ~5-10MB |
| Sent to server | β No | β No |
Demo: localStorage vs sessionStorage
HTML
<div>
<div style='display:flex;gap:8px;margin-bottom:8px;'>
<input id='ls-key' type='text' value='username' placeholder='Key' style='flex:1;padding:6px;border:1px solid #cbd5e1;border-radius:4px;'>
<input id='ls-value' type='text' value='Alice' placeholder='Value' style='flex:1;padding:6px;border:1px solid #cbd5e1;border-radius:4px;'>
</div>
<div style='display:flex;gap:8px;flex-wrap:wrap;margin-bottom:8px;'>
<button id='ls-set'>Set (localStorage)</button>
<button id='ss-set'>Set (sessionStorage)</button>
<button id='ls-get'>Get (localStorage)</button>
<button id='ls-del'>Delete (localStorage)</button>
<button id='ls-clear'>Clear All</button>
</div>
<pre id='ls-out' style='background:#f1f5f9;padding:12px;border-radius:6px;'></pre>
</div> JavaScript
const out = document.getElementById('ls-out');
function display() {
let info = 'localStorage:\\n';
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
info += ' ' + key + ' = ' + localStorage.getItem(key) + '\\n';
}
info += '(total: ' + localStorage.length + ' items)\\n';
info += '---\\n';
info += 'sessionStorage:\\n';
for (let i = 0; i < sessionStorage.length; i++) {
const key = sessionStorage.key(i);
info += ' ' + key + ' = ' + sessionStorage.getItem(key) + '\\n';
}
info += '(total: ' + sessionStorage.length + ' items)';
out.textContent = info;
}
document.getElementById('ls-set').onclick = function() {
const key = document.getElementById('ls-key').value;
const value = document.getElementById('ls-value').value;
localStorage.setItem(key, value);
display();
};
document.getElementById('ss-set').onclick = function() {
const key = document.getElementById('ls-key').value;
const value = document.getElementById('ls-value').value;
sessionStorage.setItem(key, value);
display();
};
document.getElementById('ls-get').onclick = function() {
const key = document.getElementById('ls-key').value;
const val = localStorage.getItem(key);
out.textContent = 'localStorage.getItem(' + key + '') = ' + (val !== null ? val : '(null)');
};
document.getElementById('ls-del').onclick = function() {
localStorage.removeItem(document.getElementById('ls-key').value);
display();
};
document.getElementById('ls-clear').onclick = function() {
localStorage.clear();
sessionStorage.clear();
display();
};
display(); Live Output Window
Storing Objects
Storage only supports strings. Use JSON.stringify/parse for objects:
// Save
const user = { name: 'Alice', role: 'admin', scores: [95, 87, 92] };
localStorage.setItem('user', JSON.stringify(user));
// Load
const saved = JSON.parse(localStorage.getItem('user'));
console.log(saved.name); // "Alice"
Demo: Storing Objects
HTML
<div>
<button id='save-object'>Save User Object</button>
<button id='load-object'>Load User Object</button>
<button id='update-scores'>Add Score</button>
<pre id='obj-out' style='background:#f1f5f9;padding:12px;border-radius:6px;'></pre>
</div> JavaScript
const out = document.getElementById('obj-out');
document.getElementById('save-object').onclick = function() {
const user = {
name: 'Alice',
role: 'admin',
scores: [95, 87, 92],
lastLogin: new Date().toISOString()
};
localStorage.setItem('user', JSON.stringify(user));
out.textContent = 'Saved: ' + JSON.stringify(user, null, 2);
};
document.getElementById('load-object').onclick = function() {
const data = localStorage.getItem('user');
if (!data) {
out.textContent = 'No user object found β save one first';
return;
}
const user = JSON.parse(data);
out.textContent =
'Name: ' + user.name + '\\n' +
'Role: ' + user.role + '\\n' +
'Scores: ' + user.scores.join(', ') + '\\n' +
'Last login: ' + user.lastLogin;
};
document.getElementById('update-scores').onclick = function() {
const data = localStorage.getItem('user');
if (!data) {
out.textContent = 'No user found β save one first';
return;
}
const user = JSON.parse(data);
const newScore = Math.floor(Math.random() * 100);
user.scores.push(newScore);
localStorage.setItem('user', JSON.stringify(user));
out.textContent = 'Added score: ' + newScore + '\\n' + 'Scores: ' + user.scores.join(', ');
}; Live Output Window
The storage Event
When localStorage changes in another tab, a storage event fires:
window.addEventListener('storage', function(e) {
console.log(`${e.key} changed from ${e.oldValue} to ${e.newValue}`);
console.log('Origin:', e.url);
console.log('Storage area:', e.storageArea);
});
This allows cross-tab synchronization.
Error Handling
Storage can throw errors (quota exceeded, private browsing):
try {
localStorage.setItem('key', 'value');
} catch (e) {
if (e.name === 'QuotaExceededError') {
console.error('Storage is full!');
}
// Or: storage is disabled (private browsing)
}
Storage Capacity
Test how much storage is available:
function testStorageSize() {
let data = 'x'.repeat(1024); // 1KB
let total = 0;
try {
while (true) {
localStorage.setItem('test', data.repeat(total + 1));
total++;
}
} catch (e) {
localStorage.removeItem('test');
return total + 'MB';
}
}
Practical: Theme Preference
function setTheme(theme) {
localStorage.setItem('theme', theme);
document.body.className = theme;
}
function loadTheme() {
const saved = localStorage.getItem('theme');
if (saved) {
document.body.className = saved;
}
}
// Load on page load
loadTheme();
Key Takeaways
localStoragepersists indefinitely;sessionStoragelives per-tab- Both are key-value with string-only values β use JSON for objects
- ~5-10MB capacity (much more than cookiesβ 4KB)
- Not sent with HTTP requests (unlike cookies)
- The
storageevent syncs changes across tabs - Always wrap in
try/catchβ quota exceeded errors are common - Use for preferences, draft saves, cached data, and client-side state