JS localStorage API Guide: A Complete Tutorial

Learn how to store, retrieve, update, and remove data in the browser using the localStorage API with clear examples and practical patterns.

6 min read

localStorage is a built-in browser API that stores key-value pairs directly in the user's browser. The data stays even after closing the tab, restarting the browser, or rebooting the computer.

It is the simplest way to save user preferences, form progress, or any small piece of state without a backend server.

Here is the smallest useful localStorage program you can write:

javascriptjavascript
localStorage.setItem("username", "Rune");
console.log(localStorage.getItem("username"));

The first line saves the string "Rune" under the key "username". The second line reads it back. If you close the browser tab, open a new one, and run only the getItem line, it still prints "Rune".

What localStorage actually stores

localStorage belongs to the browser's Web Storage API. It is a simple key-value dictionary attached to your site's origin. Every key and every value is a string. There is no schema, no data types, and no expiration.

PropertyBehavior
ScopeOne origin (protocol + domain + port)
CapacityAbout 5 MB per origin
Data typeStrings only
LifetimePermanent, until explicitly deleted
SharedYes, across all tabs of the same origin
AccessSynchronous (blocks the main thread for large operations)

Because localStorage is synchronous, reading a single key is instant, but writing huge JSON blobs in a loop can briefly freeze the page. Keep stored values small.

The core methods

localStorage gives you five methods, but four cover virtually every real-world use case:

MethodWhat it does
setItem(key, value)Save a string value under a key
getItem(key)Read a stored value, returns null if missing
removeItem(key)Delete one key and its value
clear()Delete every key for your origin

Saving and reading data

The setItem method takes a key name and a string value. If the key already exists, the old value is overwritten.

javascriptjavascript
localStorage.setItem("theme", "dark");
localStorage.setItem("fontSize", "16");
localStorage.setItem("notifications", "true");
 
const theme = localStorage.getItem("theme");
const missing = localStorage.getItem("doesNotExist");
 
console.log(theme);
console.log(missing);

Running this code prints two values. The first getItem retrieves the saved theme. The second asks for a key that was never set, so it returns null.

texttext
dark
null

The getItem call for "doesNotExist" returns null because that key was never set. Since getItem returns null for missing keys, never call string methods on its result without checking first.

Removing data

removeItem deletes a single key. The clear method wipes everything for your origin.

javascriptjavascript
localStorage.removeItem("fontSize");
console.log(localStorage.getItem("fontSize"));
 
localStorage.clear();
console.log(localStorage.getItem("theme"));

First removeItem deletes the fontSize key, then clear wipes every remaining key for this origin. Both getItem calls now return null since nothing is left:

texttext
null
null

Be careful with clear(). It removes every key your site has ever stored, including ones set by third-party scripts or libraries on the same origin.

Reading and writing non-string values

Since localStorage only accepts strings, you must convert numbers, booleans, and objects manually.

Numbers and booleans

javascriptjavascript
localStorage.setItem("visits", String(42));
const visits = Number(localStorage.getItem("visits"));
console.log(visits + 1);
 
localStorage.setItem("subscribed", "true");
const subscribed = localStorage.getItem("subscribed") === "true";
console.log(subscribed);

The code converts a stored number back to a real number for math, and compares a stored string to "true" for a real boolean. Here is the output:

texttext
43
true

Call Number() on the value you get back from storage. For booleans, compare against the string "true". Any other string becomes false.

Objects and arrays

localStorage cannot store objects directly. Serialize them with JSON.stringify before saving and deserialize with JSON.parse when reading. The companion article Storing Complex Objects in JS localStorage Guide covers this pattern in depth.

javascriptjavascript
const user = { name: "Rune", level: 5 };
localStorage.setItem("user", JSON.stringify(user));
 
const saved = JSON.parse(localStorage.getItem("user"));
console.log(saved.name);

After saving the object as JSON and reading it back, the name property is accessible again. Here is the result:

texttext
Rune

Always wrap JSON.parse in a try/catch block in real applications. If the stored value is corrupted or was written by buggy code, parsing will throw an error and break your script.

Reacting to changes across tabs

When you write to localStorage in one tab, other open tabs from the same origin receive a storage event. This keeps multiple tabs in sync without polling.

javascriptjavascript
window.addEventListener("storage", (event) => {
  console.log(`Key changed: ${event.key}`);
  console.log(`Old value:   ${event.oldValue}`);
  console.log(`New value:   ${event.newValue}`);
});

The storage event only fires in tabs that did not trigger the change. If Tab A calls setItem, the event fires in Tab B, not Tab A.

Checking if localStorage is available

Some browsers block localStorage in private or incognito mode. Calling setItem can throw an error. Test availability once before relying on it:

javascriptjavascript
function storageAvailable() {
  try {
    const testKey = "__storage_test__";
    localStorage.setItem(testKey, testKey);
    localStorage.removeItem(testKey);
    return true;
  } catch {
    return false;
  }
}

If storageAvailable returns false, your code should fall back to in-memory storage or show a message to the user.

When to use localStorage

localStorage is the right choice when data needs to survive longer than a single page visit. Common use cases include user preferences like theme and font size, saving form drafts so work is not lost on refresh, caching API responses to avoid redundant network requests, tracking whether a user has seen a tutorial or dismissed a banner, and keeping a guest shopping cart for unauthenticated users.

For data that should disappear when the tab closes, use sessionStorage instead. For data the server needs to read automatically, use cookies instead of localStorage.

Common mistakes

  • Storing objects without JSON.stringify saves the string "[object Object]" instead of your data.
  • Not checking for null after getItem. Calling methods on null throws a TypeError.
  • Using clear() carelessly removes data from every script on your origin, not just your own code.
  • Storing too much data hits the 5 MB per-origin limit. Wrap setItem in try/catch.
  • Assuming localStorage is always available. Private browsing mode can block it.

Quick reference

OperationCode
Save a valuelocalStorage.setItem("key", "value")
Read a valuelocalStorage.getItem("key")
Delete one keylocalStorage.removeItem("key")
Delete all keyslocalStorage.clear()
Check availabilityWrap setItem in try/catch
Listen for changeswindow.addEventListener("storage", handler)
Rune AI

Rune AI

Key Insights

  • localStorage stores key-value pairs as strings that persist until explicitly removed.
  • Use setItem, getItem, removeItem, and clear for all operations.
  • Always handle the string-only limitation by converting numbers, booleans, and objects explicitly.
  • Wrap JSON.parse calls in try/catch to avoid crashes on corrupted data.
  • Listen for the storage event to keep multiple tabs in sync.
RunePowered by Rune AI

Frequently Asked Questions

How much data can I store in localStorage?

Most browsers limit localStorage to about 5 MB per origin. This is enough for user preferences, cached data, and small state snapshots, but not for large files or databases.

Does localStorage work across tabs?

Yes. localStorage is shared across all tabs and windows from the same origin. If you write a value in one tab, another tab from the same site can read it immediately.

Does localStorage expire?

No. Data in localStorage stays forever unless the user clears their browser data or your code explicitly removes it. For data that should expire, use sessionStorage or cookies instead.

Can I store objects directly in localStorage?

No. localStorage only stores strings. To store objects or arrays, convert them to a JSON string with JSON.stringify() before saving and parse them back with JSON.parse() when reading.

Conclusion

localStorage is the simplest way to keep data across page reloads and browser sessions without a server. Use setItem and getItem for basic reads and writes, remember that values are always strings, and handle the storage event if your app opens multiple tabs. For temporary data or objects, combine localStorage with JSON serialization or use sessionStorage.