ComparisonWeb

localStorage vs cookies

localStorage vs cookies: storage limits, server access, and why session tokens still often belong in cookies.

Last updated

The short answer

localStorage is the right place for client-only data the server never needs to see — UI preferences, cached API responses, draft form state. Cookies remain the better fit for anything involving authentication, because they're the only mechanism sent automatically to the server and can be marked HttpOnly, which JavaScript-based storage can never do.

DimensionlocalStorageCookies
Storage limit~5-10MB per origin~4KB per cookie
Sent to serverNever, JS-onlyAutomatically, on every matching request
Accessible to JSAlwaysOnly if not marked HttpOnly
ExpiryPersists until explicitly clearedSet expiry, or session-only
XSS exposureFully readable by any injected scriptHidden from JS if HttpOnly is set
Best forPreferences, cached data, draftsAuth tokens, session identifiers

Choose localStorage when

  • →You're storing UI state or preferences (theme, sidebar collapsed) that only your client-side JavaScript ever needs.
  • →You need to cache a meaningfully sized payload — an API response, a draft document — well past the ~4KB a cookie allows.
  • →The data has no business being sent to the server on every request, which is exactly what cookies do automatically.

Choose Cookies when

  • →You're storing a session token or auth credential and want it marked HttpOnly so client-side JavaScript — including an XSS payload — can never read it.
  • →The server needs the value automatically on every request without your frontend code manually attaching it.
  • →You need fine control over expiry, domain and path scoping that the Set-Cookie mechanism gives you natively.

The catch nobody mentions

localStorage has no HttpOnly equivalent — anything stored there is readable by any script running on the page, including a malicious one injected via XSS. Storing a JWT or session token in localStorage is a common but genuine security mistake, since the moment an attacker gets script execution on your page, they get the token too.

Common mistakes

  • localStorage.setItem("token", jwt)

    Anything in localStorage is readable by any JavaScript on the page, so a single cross-site scripting flaw or a compromised dependency exfiltrates the token. An HttpOnly cookie is unreadable from script by design.

  • document.cookie = "session=" + id

    Sets a cookie with no Secure, HttpOnly or SameSite attributes, so it travels over plain HTTP, is readable from script, and is sent on cross-site requests. Session cookies should be set by the server with all three.

  • localStorage.setItem("prefs", prefs)

    Storage holds strings only, so an object becomes the literal text [object Object] and is unrecoverable. It has to be serialised with JSON.stringify and parsed on the way back.

    localStorage.setItem("prefs", JSON.stringify(prefs))

Questions

Where should an auth token live?

In an HttpOnly, Secure, SameSite cookie set by the server. That combination means script cannot read it, it never travels unencrypted, and it is not attached to cross-site requests — three protections localStorage cannot offer.

Is localStorage sent to the server?

Never. It is purely client-side, which is its main advantage over cookies for data the server does not need — no bytes added to every single request.

How much can each hold?

Around 5MB for localStorage per origin, against roughly 4KB per cookie with a limit on how many an origin may set. That difference alone decides most cases where the data is more than an identifier.

Does localStorage persist forever?

Until cleared, in principle, but browsers evict it under storage pressure and in some privacy modes, and it is wiped when a user clears site data. Treat it as a cache that can vanish rather than as storage you own.

What about sessionStorage and IndexedDB?

sessionStorage has the same API and is scoped to one tab, which suits per-tab state. IndexedDB is asynchronous and holds far more, and is the right choice once you are storing structured data rather than a few keys.

Related in Comparisons