localStorage in JavaScript: keeping data from one visit to the next

localStorage keeps strings in the browser with no expiry date. Five megabytes, synchronous access, and nothing sensitive allowed inside it.
3 min read
Believemy logo

A dark theme picked yesterday, a cart abandoned last week, a banner already dismissed: this information has to survive the browser closing, without an account and without a server.

Browsers set aside a small space per site for exactly that, with a deliberately tiny interface: read, write, wipe, and nothing more.


Definition

localStorage is a key-value store attached to an origin, meaning the trio of protocol, domain and port. Data stays there with no expiry date, until a script or the visitor wipes it.

JAVASCRIPT
localStorage.setItem("theme", "dark");

console.log(localStorage.getItem("theme"));     // "dark"
console.log(localStorage.getItem("unknown"));   // null

localStorage.removeItem("theme");
localStorage.clear();                           // the whole space for the origin

A missing key returns null, never undefined: the distinction matters as soon as the value you read is used as a condition.


Everything becomes text

The store only holds strings. A value of any other type is converted silently, which produces surprises when you read it back.

JAVASCRIPT
localStorage.setItem("loggedIn", true);
console.log(localStorage.getItem("loggedIn") === true);   // false
console.log(typeof localStorage.getItem("loggedIn"));     // "string"

localStorage.setItem("cart", JSON.stringify({ lines: 3 }));
const cart = JSON.parse(localStorage.getItem("cart"));
console.log(cart.lines + 1);                              // 4

An object therefore goes through JSON on the way in and on the way out. The string "false" read back stays on the Truthy and falsy true side, which is enough to flip an entire condition.

Good to know

Access is synchronous: every read and every write blocks the main thread. Storing a large object on each keystroke is enough to make an interface stutter.


What does not belong in it

Every script the page loads can read this space, including a third-party script or one injected through a vulnerability. Three categories should stay out.

  • An authentication token: readable by any script, where a Cookie marked HttpOnly is not.
  • Personal data: it stays on the machine long after the visit, sometimes on a shared computer.
  • Large volumes: the limit sits around five megabytes per origin, and a local database belongs in IndexedDB.

Writing can also fail: quota exceeded, private browsing, storage turned off. A call wrapped in a try block keeps a whole page from dying on that one line.


Frequently asked questions

Question

How do I know another tab changed a value?

The browser fires a storage event on the window, carrying the old and the new value. One useful quirk: it only fires in the other documents of the same origin, never in the one that just wrote. That is what lets you propagate a sign-out across every open tab.


Question

Does the data ever disappear?

There is no expiry date, but nothing guarantees permanence either. Visitors can clear their browser, and some browsers wipe script-written storage on their own after a long stretch without a visit. Treat this space as a convenience, never as the only copy of a piece of data.


Question

localStorage or sessionStorage?

Both share the exact same interface, only the lifetime changes. Pick the first one for a preference that has to hold from one visit to the next, and sessionStorage for data that only makes sense inside the current tab, such as the step of a multi-page form.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.