LocalStorage

Course: JavaScript Intermediate

Lesson 12: LocalStorage

Level

Intermediate

Estimated Reading Time

10–15 minutes

Goal

By the end of this lesson, the learner will be able to:

  • Save, retrieve, and delete data from localStorage using setItem, getItem, and removeItem
  • Use JSON.stringify and JSON.parse to store and retrieve objects and arrays
  • Explain when localStorage is appropriate and what its limitations are

Frontend Development Context

LocalStorage lets you persist data in the user's browser across page reloads and browser sessions. This is how apps remember a user's theme preference, save a form draft, or keep a to-do list without a backend. Unlike cookies, localStorage is purely a client-side feature and is not sent to the server with each request.

Understanding localStorage is a stepping stone toward understanding more complex state persistence tools. Once you know how to save and retrieve objects using JSON, you have a practical pattern that works in any vanilla JavaScript app and is easy to replace with a database or API when the app grows.

Explanation

localStorage is a key-value store built into the browser. Every key and every value must be a string. You interact with it using four main methods: setItem(key, value) to save data, getItem(key) to retrieve it, removeItem(key) to delete a specific entry, and clear() to delete everything.

Because localStorage only stores strings, you cannot store objects or arrays directly. Storing an object without serializing it will save the string "[object Object]". The solution is to use JSON.stringify() to convert the value to a JSON string before saving, and JSON.parse() to convert it back to a JavaScript value when reading.

LocalStorage data persists until explicitly deleted by JavaScript or by the user clearing their browser storage. It is not cleared when the browser tab or window closes, unlike sessionStorage (which only lasts for the current session).

There are limitations. LocalStorage is synchronous — operations block the main thread. For large datasets, this can slow down the page. It has a storage limit of around 5 MB per origin. Sensitive data should never be stored in localStorage because it is accessible to any JavaScript on the same domain (making it vulnerable to XSS attacks).

Code Example

This example saves and retrieves a user preferences object, and manages a list of saved lessons in localStorage.

// Save a string value
localStorage.setItem("theme", "dark");

// Retrieve it
const theme = localStorage.getItem("theme");
console.log(theme); // "dark"

// Store an object — must JSON.stringify it first
const preferences = {
  theme: "dark",
  fontSize: 16,
  language: "en"
};
localStorage.setItem("preferences", JSON.stringify(preferences));

// Retrieve and parse it back to an object
const saved = localStorage.getItem("preferences");
const prefs = saved ? JSON.parse(saved) : null;
console.log(prefs?.theme);    // "dark"
console.log(prefs?.fontSize); // 16

// Store an array of completed lesson IDs
const completed = [1, 3, 5, 7];
localStorage.setItem("completedLessons", JSON.stringify(completed));

const storedLessons = JSON.parse(localStorage.getItem("completedLessons") || "[]");
console.log(storedLessons); // [1, 3, 5, 7]

// Remove one key
localStorage.removeItem("theme");
console.log(localStorage.getItem("theme")); // null

Code Explanation

localStorage.setItem("theme", "dark") saves the string "dark" under the key "theme". getItem("theme") retrieves it. These are the most basic operations.

Storing preferences requires JSON.stringify(preferences) to convert the object to a JSON string. Without this, you would store "[object Object]" which cannot be parsed back. When reading, JSON.parse(saved) converts the string back into a JavaScript object.

The saved ? JSON.parse(saved) : null pattern guards against parsing null. If the key does not exist in localStorage, getItem returns null, and calling JSON.parse(null) returns null without an error — but it is good practice to be explicit about the fallback.

|| "[]" in JSON.parse(localStorage.getItem("completedLessons") || "[]") ensures that if the key does not exist, JSON.parse receives a valid JSON string ("[]") and returns an empty array rather than throwing.

Pattern Highlights

Positive Pattern: Always wrap localStorage reads in a guard that handles null (key not found) or invalid JSON. Failing to do so can cause uncaught errors when users have no existing storage or their storage has been corrupted.

⚠️ Neutral Note: LocalStorage is synchronous and blocks the main thread. For large amounts of data (thousands of records), consider IndexedDB, which is asynchronous.

Negative Pattern: Never store sensitive information such as authentication tokens, passwords, or personal data in localStorage. It is readable by any script on the same origin and is a common XSS target.

Common Mistakes

Mistake 1: Storing an object without JSON.stringify

Saving an object directly causes it to be stored as "[object Object]".

const user = { name: "Alex" };
localStorage.setItem("user", user);
const retrieved = localStorage.getItem("user");
console.log(retrieved); // "[object Object]" — useless string

Always use JSON.stringify before storing non-string values and JSON.parse when reading them back.

Mistake 2: Not handling the case when getItem returns null

Calling JSON.parse(null) or accessing properties on null without a guard.

const data = JSON.parse(localStorage.getItem("settings"));
console.log(data.theme); // TypeError if "settings" key doesn't exist

getItem returns null when the key is absent. Check for null or provide a fallback: JSON.parse(localStorage.getItem("settings") || "{}") .

Mistake 3: Forgetting that localStorage only exists in the browser

Trying to use localStorage in a server-side rendering environment or Node.js.

// In a Next.js server component or Node.js script:
localStorage.setItem("key", "value"); // ReferenceError: localStorage is not defined

LocalStorage is a browser API. In server-side environments, it does not exist. Guard with typeof localStorage !== "undefined" or only access it inside browser-side event handlers.

Quick Recap

  • localStorage.setItem(key, value) saves a string; getItem(key) retrieves it; removeItem(key) deletes it
  • Objects and arrays must be serialized with JSON.stringify before saving and deserialized with JSON.parse when reading
  • getItem returns null for missing keys — always guard against this before parsing or accessing properties
  • LocalStorage is persistent (survives browser close), limited to about 5 MB, and should never hold sensitive data

Ready to test your understanding? Take the quiz to reinforce what you learned.

© 2026 Ant Skillsv.26.07.07-23:01