Browser Storage
localStorage
- Persists until explicitly cleared.
- Accessible only via JavaScript.
- ~5-10MB per origin.
- Not sent to server automatically.
ts
localStorage.setItem('theme', 'dark');
localStorage.getItem('theme'); // 'dark'
localStorage.removeItem('theme');
localStorage.clear();sessionStorage
- Cleared when the browser tab is closed.
- Not shared across tabs.
- Same API as localStorage.
ts
sessionStorage.setItem('draftForm', JSON.stringify(formData));
// survives page refresh in same tab, gone when tab closesCookies
- Sent to the server on every request automatically.
- Can be set by server (
Set-Cookieheader) or client. - Configurable expiry, scope, and security flags.
- ~4KB limit.
ts
// client-side
document.cookie = 'name=Alice; max-age=3600; path=/';
// server sets httpOnly cookie (JS can't read)
res.setHeader('Set-Cookie', 'token=abc123; HttpOnly; Secure; SameSite=Strict; Max-Age=86400');Security flags for cookies
| Flag | Effect |
|---|---|
HttpOnly | Not accessible via JS - prevents XSS token theft |
Secure | Only sent over HTTPS |
SameSite=Strict | Never sent on cross-site requests - prevents CSRF |
SameSite=Lax | Sent on top-level navigations only |
Comparison
| localStorage | sessionStorage | Cookie | |
|---|---|---|---|
| Capacity | ~5-10MB | ~5MB | ~4KB |
| Expiry | Never | Tab close | Configurable |
| Sent to server | No | No | Yes (auto) |
| Accessible via JS | Yes | Yes | Yes (if not httpOnly) |
| Cross-tab | Yes | No | Yes |
Never store JWTs or sensitive tokens in localStorage - it's vulnerable to XSS. Use
httpOnlycookies instead - JavaScript can't read them even if your site is compromised.
updated
did you know it?