LocalStorage vs SessionStorage: Key Differences

LocalStorage is persistent, while SessionStorage is cleared when the tab closes.

LocalStorage and SessionStorage

LocalStorage and SessionStorage are two browser storage mechanisms that let JavaScript save data on the client side without cookies. They share an identical API but differ critically in how long data persists and how it is scoped across tabs and windows.

What Is LocalStorage

LocalStorage is a key-value store built into every modern browser that persists data with no expiry date. Data written to LocalStorage survives browser restarts, system reboots, and extended periods of inactivity. It remains until JavaScript explicitly deletes it or the user manually clears their browser storage through the browser settings. This makes it suitable for any data that should be available the next time a user returns to your site.

LocalStorage is scoped to the origin, meaning the combination of scheme, domain, and port. Data stored at https://example.com is accessible from any tab or window on that same origin, but not from https://api.example.com or http://example.com. It is never sent to the server automatically with HTTP requests, which distinguishes it from cookies.

LocalStorage JavaScript API:
// Store a value
localStorage.setItem('theme', 'dark');

// Read a value
const theme = localStorage.getItem('theme'); // 'dark'

// Store an object (must serialize to string)
localStorage.setItem('user', JSON.stringify({ id: 42, name: 'Alice' }));

// Read an object back
const user = JSON.parse(localStorage.getItem('user'));

// Delete a specific key
localStorage.removeItem('theme');

// Clear all keys for this origin
localStorage.clear();

// Check the number of stored items
console.log(localStorage.length);

What Is SessionStorage

SessionStorage uses an identical API to LocalStorage but applies a much shorter scope to stored data. Data is tied to the specific browser tab or window in which it was created and is automatically cleared the moment that tab or window is closed. It is completely isolated between tabs, meaning two tabs open on the same site each have their own independent SessionStorage that cannot read each other's data.

This isolation makes SessionStorage ideal for state that should not carry over between separate browsing sessions or between different tabs a user has open simultaneously. A multi-step checkout flow, a wizard that tracks which step the user is on, or form data that should not persist if the user closes and reopens the browser are all good candidates for SessionStorage.

SessionStorage JavaScript API (identical to LocalStorage):
// Store a value
sessionStorage.setItem('step', '2');

// Read a value
const step = sessionStorage.getItem('step'); // '2'

// Store form progress
sessionStorage.setItem('formData', JSON.stringify({ name: 'Alice', email: '' }));

// Delete a specific key
sessionStorage.removeItem('step');

// Cleared automatically when the tab closes

LocalStorage vs SessionStorage: Full Comparison

FeatureLocalStorageSessionStorage
PersistencePermanent until explicitly deleted by JavaScript or the userCleared automatically when the tab or window is closed
ScopeSame origin across all tabs and windowsSame origin within the same tab only
Tab SharingShared across all tabs on the same origin simultaneouslyIsolated per tab. Two tabs on the same site cannot access each other's SessionStorage.
Storage LimitApproximately 5 to 10 MB per origin depending on the browserApproximately 5 to 10 MB per origin per tab
JavaScript AccessReadable and writable by any JavaScript running on the same originReadable and writable by JavaScript in the same tab on the same origin
Sent to ServerNever. The server has no visibility into LocalStorage contents.Never. The server has no visibility into SessionStorage contents.
Survives Page RefreshYesYes. A page refresh does not count as closing the tab.
Survives Browser RestartYesNo. Closing the browser clears all SessionStorage.
Best ForUser preferences, themes, language settings, cached non-sensitive dataMulti-step form progress, wizard steps, tab-specific UI state, temporary session data

LocalStorage vs SessionStorage vs Cookies

All three mechanisms store data on the client side, but they serve different purposes and have important differences in how data is transmitted, how long it persists, and how much can be stored. Choosing the right one depends on whether the server needs to see the data, how long it should last, and how sensitive it is.

FeatureLocalStorageSessionStorageCookies
Storage Capacity5 to 10 MB per origin5 to 10 MB per origin per tabApproximately 4 KB per cookie
Sent to ServerNoNoYes, automatically with every matching HTTP request
Expiry ControlNever expires unless explicitly clearedClears when the tab closesConfigurable via Expires or Max-Age attributes
JavaScript AccessYes, full read and write accessYes, full read and write accessYes, unless the HttpOnly attribute is set
Server AccessNot accessible by the serverNot accessible by the serverSent in the Cookie header on every request
Cross-Subdomain AccessNo. Scoped to exact origin.No. Scoped to exact origin and tab.Configurable via the Domain attribute
XSS ExposureHigh. Readable by any injected script.High. Readable by any injected script in the same tab.Protected if HttpOnly is set
Best ForClient-side preferences and non-sensitive cached dataTemporary tab-specific stateServer-side sessions, authentication tokens, cross-subdomain sharing

Security Considerations

Both LocalStorage and SessionStorage are accessible to any JavaScript running on the same origin. This creates a significant risk in the context of cross-site scripting (XSS) attacks. If an attacker successfully injects malicious JavaScript into your page, that script can read everything stored in LocalStorage and SessionStorage and exfiltrate it to a remote server. Unlike HttpOnly cookies, there is no attribute you can set to make these storage mechanisms invisible to JavaScript.

  • Both are same-origin scoped: Data is only accessible to JavaScript running on the exact same scheme, domain, and port. A script from a different origin cannot read your storage, but any script from your own origin, including injected scripts, can.
  • Neither is sent to the server automatically: Unlike cookies, the server never sees the contents of LocalStorage or SessionStorage unless your JavaScript explicitly reads the value and includes it in an API request.
  • XSS is the primary threat: If your site has any XSS vulnerability, anything stored in LocalStorage or SessionStorage can be stolen. See XSS explained for how these attacks work and how to prevent them.
  • Avoid storing authentication tokens in LocalStorage for sensitive applications: If a token stored in LocalStorage is stolen via XSS, the attacker gains persistent access until the token expires. An HttpOnly cookie carrying the same token cannot be read by JavaScript at all, eliminating this attack vector.
  • Never store passwords or payment data: These should never exist in client-side storage of any kind. If they must be held temporarily, keep them only in JavaScript variables that are not persisted and cannot be accessed after the page session ends.

When to Use Each

The right storage mechanism depends on three questions: how long should the data last, does the server need it, and how sensitive is it?

  • Use LocalStorage for user preferences such as theme selection, language setting, or display density that should persist between visits. Also suitable for caching non-sensitive API responses that improve performance on return visits, and for remembering non-critical application state across sessions.
  • Use SessionStorage for multi-step form progress where data should be lost if the user abandons the session, for tracking which step of a wizard the user is on, for tab-specific UI state such as which panel is expanded, and for any data that should not carry over to other tabs or future visits.
  • Use cookies for authentication tokens that the server needs to read on every request, for session identifiers that should be protected from JavaScript with the HttpOnly attribute, and for any data that needs to be shared across subdomains using the Domain attribute.

Frequently Asked Questions

  1. Does incognito mode clear LocalStorage?
    In incognito or private browsing mode, LocalStorage behaves more like SessionStorage. Data written during a private session is cleared when the private window closes. It does not persist to subsequent sessions, whether private or regular. Additionally, incognito mode starts with a fresh storage context that does not inherit any data from your regular browsing session, and any data written during incognito mode is not visible in your regular session.
  2. Can LocalStorage hold objects or arrays?
    LocalStorage and SessionStorage can only store strings. To store objects or arrays, serialise them to a JSON string using JSON.stringify() before writing, and deserialise them back using JSON.parse() when reading. If you attempt to store a non-string value directly, it will be converted to a string automatically, which usually produces unexpected results. For example, storing an array without stringifying it will result in the string representation of the array being stored rather than the array structure.
  3. Is LocalStorage accessible across subdomains?
    No. LocalStorage is strictly scoped to the exact origin, which means the combination of scheme, domain, and port must all match. Data stored at https://example.com is not accessible at https://blog.example.com or https://api.example.com, even though they share the same root domain. If you need to share data across subdomains, cookies with the Domain attribute set to the root domain are the appropriate mechanism.
  4. What happens to SessionStorage when a tab is duplicated?
    When a user duplicates a tab in most browsers, the new tab receives a copy of the SessionStorage from the original tab at the moment of duplication. After that point, the two tabs have completely independent copies and changes in one do not affect the other. This behaviour can be surprising if you assume SessionStorage is always unique per tab, but it is consistent with the specification. If you need guaranteed isolation between tabs, you should not rely on SessionStorage alone and should include additional identifiers in your state management.
  5. How much data can LocalStorage actually hold?
    Most modern browsers allow approximately 5 MB of LocalStorage per origin, though some browsers offer up to 10 MB. The limit applies to the total of all keys and values combined for a given origin, not per individual item. When storage is full, attempting to write more data throws a QuotaExceededError, which your code should catch and handle gracefully. You can check current usage programmatically, though the exact API for this varies by browser. For applications that need to store larger amounts of data on the client side, IndexedDB is a more appropriate choice as it supports much larger quotas and binary data.

Conclusion

LocalStorage and SessionStorage provide convenient, straightforward client-side storage with a simple key-value API that requires no configuration. LocalStorage persists data indefinitely across sessions and is ideal for user preferences, themes, and non-sensitive cached data. SessionStorage is scoped to a single tab and is cleared on close, making it perfect for temporary, session-specific state such as multi-step form progress. Neither is sent to the server automatically, making both faster and lighter than cookies for purely client-side data. However, both are vulnerable to XSS attacks in a way that HttpOnly cookies are not, so sensitive authentication tokens are better stored in HttpOnly cookies for any application where security is a priority. Explore cookies vs sessions, cookie security attributes, and session vs token authentication for a complete picture of web storage and authentication options.