Browsers provide several mechanisms to store data on the client. Choose the right one based on lifetime, size, and security needs.

Comparison

Feature localStorage sessionStorage Cookies
Lifetime Until cleared Tab session Configurable expiry
Size limit ~5–10 MB ~5–10 MB ~4 KB
Sent to server No No Yes (every request)
API Simple key-value Simple key-value document.cookie

localStorage

Persists across browser sessions:

  // Set
localStorage.setItem('theme', 'dark');
localStorage.setItem('user', JSON.stringify({ name: 'Alice' }));

// Get
let theme = localStorage.getItem('theme'); // 'dark'
let user = JSON.parse(localStorage.getItem('user'));

// Remove
localStorage.removeItem('theme');
localStorage.clear(); // remove all

// Check existence
if (localStorage.getItem('token') === null) {
    console.log('Not logged in');
}
  

sessionStorage

Same API as localStorage, but data is cleared when the tab closes:

  sessionStorage.setItem('formDraft', JSON.stringify(formData));

let draft = JSON.parse(sessionStorage.getItem('formDraft'));
  

Storage Events

Other tabs can listen for storage changes:

  window.addEventListener('storage', (e) => {
    console.log(e.key, e.oldValue, e.newValue);
    // Fires in OTHER tabs, not the one that made the change
});
  

Cookies

  // Set (basic)
document.cookie = 'username=Alice; max-age=3600; path=/; SameSite=Strict';

// Read (returns all cookies as one string)
console.log(document.cookie); // 'username=Alice; other=value'

// Helper to parse
function getCookie(name) {
    return document.cookie
        .split('; ')
        .find(row => row.startsWith(name + '='))
        ?.split('=')[1];
}
  

Modern apps prefer HttpOnly cookies set by the server for auth tokens (not accessible via JavaScript).

Practical Example: Theme Toggle

  const THEME_KEY = 'app-theme';

function getTheme() {
    return localStorage.getItem(THEME_KEY) || 'light';
}

function setTheme(theme) {
    localStorage.setItem(THEME_KEY, theme);
    document.body.dataset.theme = theme;
}

setTheme(getTheme());

document.querySelector('#toggle').addEventListener('click', () => {
    setTheme(getTheme() === 'light' ? 'dark' : 'light');
});
  

Security Best Practices

  • Never store sensitive tokens in localStorage (vulnerable to XSS)
  • Prefer HttpOnly, Secure cookies for authentication
  • Validate and sanitize data read from storage
  • Use SameSite attribute on cookies to mitigate CSRF
  • Store minimal data; use server-side storage for sensitive information

Browser storage is ideal for user preferences, UI state, and non-sensitive cached data.