localStorage and sessionStorage are simple to use but easy to misuse — synchronous access can block the main thread, string-only storage silently mangles other types, and neither is a safe place for sensitive data.
1Web Storage Best Practices | JavaScript Tutorial - In-Depth Guide Part 1
localStorage persists data with no expiration date across browser restarts; sessionStorage clears when the tab (not just the page) closes.
localStorage.setItem('theme', 'dark'); // persists indefinitely
sessionStorage.setItem('draft', text); // cleared when tab closeslocalStorage vs sessionStorage
2Web Storage Best Practices | JavaScript Tutorial - In-Depth Guide Part 2
Both storage mechanisms only store strings — storing a non-string value silently coerces it via toString(), which mangles objects and arrays.
localStorage.setItem('user', { name: 'Ana' });
localStorage.getItem('user'); // '[object Object]' — data lost!Strings Only
3Web Storage Best Practices | JavaScript Tutorial - In-Depth Guide Part 3
Always serialize with JSON.stringify() before storing, and JSON.parse() after retrieving, to correctly round-trip objects and arrays.
localStorage.setItem('user', JSON.stringify({ name: 'Ana' }));
const user = JSON.parse(localStorage.getItem('user'));Serialize with JSON
4Web Storage Best Practices | JavaScript Tutorial - In-Depth Guide Part 4
The 'storage' event fires on OTHER open tabs/windows of the same origin when localStorage changes — useful for syncing state like login status across tabs.
window.addEventListener('storage', (event) => {
if (event.key === 'authToken' && event.newValue === null) {
redirectToLogin(); // user logged out in another tab
}
});Cross-Tab Sync with storage Events
5Web Storage Best Practices | JavaScript Tutorial - In-Depth Guide Part 5
Never store sensitive data (auth tokens, passwords, personal data) in localStorage — it's accessible to any JavaScript running on the page, including from an XSS vulnerability.
// Risky: readable by any injected script
localStorage.setItem('authToken', token);
// Safer: HttpOnly cookie set by the server, invisible to JSNot for Sensitive Data
6Step-by-Step Breakdown
localStorage persists data with no expiration date across browser restarts; sessionStorage clears when the tab (not just the page) closes.
Both storage mechanisms only store strings — storing a non-string value silently coerces it via toString(), which mangles objects and arrays.
Checkpoint: What happens when you pass a plain object directly to localStorage.setItem()?
- →It's coerced to the string '[object Object]'
- →The object is stored and retrieved correctly as-is
Always serialize with JSON.stringify() before storing, and JSON.parse() after retrieving, to correctly round-trip objects and arrays.
The 'storage' event fires on OTHER open tabs/windows of the same origin when localStorage changes — useful for syncing state like login status across tabs.
Checkpoint: Does the "storage" event fire in the same tab that made the localStorage change?
- →Yes, every tab including the one that made the change
- →No, only other open tabs of the same origin
Never store sensitive data (auth tokens, passwords, personal data) in localStorage — it's accessible to any JavaScript running on the page, including from an XSS vulnerability.
Next, we'll explore 'The Intersection Observer'.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Persist Accessibility Preferences Deliberately with localStorage
Saving a user's chosen preferences (like reduced motion or high contrast mode overrides) in localStorage and re-applying them on every page load ensures the accessible experience they configured persists across visits, rather than resetting each time.
SEO Implications
- 1
No Direct SEO Effect
Web Storage is client-side only and invisible to search engine crawlers; SEO relevance is limited to ensuring stored data does not break rendering when unavailable (e.g. private browsing modes).
Best Practices
Always JSON.stringify/parse Structured Data
Treating localStorage/sessionStorage as string-only storage and consistently serializing avoids silent data corruption from automatic toString() coercion.
Never Store Authentication Tokens or Sensitive Data in Web Storage
Because any script running on the page (including an injected XSS payload) can read localStorage freely, sensitive credentials belong in an HttpOnly cookie set by the server instead.
Frequent Bugs
Storing an object directly with localStorage.setItem('key', obj), then later retrieving the useless string '[object Object]' instead of the original data.
Always JSON.stringify() before storing and JSON.parse() after retrieving structured data.
Wrapping every localStorage.getItem(...) call in JSON.parse() without checking for null first, causing a "Unexpected token u in JSON" error when a key was never set.
Check for a null return value before parsing, or wrap the parse in a try/catch with a sensible default.
Real-World Examples
Syncing Logout Across Multiple Open Tabs
An app needed to redirect every open tab to the login page immediately if the user logged out in any one of them.
window.addEventListener('storage', (event) => {
if (event.key === 'authToken' && !event.newValue) {
window.location.href = '/login';
}
});
// On logout in any tab:
localStorage.removeItem('authToken');