JavaScript localStorage: Save Data in the Browser

JavaScript localStorage lets your website save small amounts of data in a user’s browser.

You can use it to remember a theme choice, save a simple shopping cart, store recently viewed items, or keep form preferences after the page reloads.

The data remains available after a page refresh and can remain available after the browser is closed and opened again.

Course Home: JavaScript Tutorial for Beginners
Previous Lesson: JavaScript Fetch API Explained
Next Lesson: JavaScript sessionStorage Explained

Quick Answer

Save a value:

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

Read it:

const theme =
    localStorage.getItem("theme");

console.log(theme);

Output:

dark

Remove one item:

localStorage.removeItem("theme");

Remove all items stored for the current origin:

localStorage.clear();

localStorage stores strings.

To save an object or array, use:

JSON.stringify()

and restore it with:

JSON.parse()

What Is localStorage in JavaScript?

localStorage is part of the browser’s Web Storage API.

It stores key-value pairs for the current origin.

Example:

localStorage.setItem(
    "userName",
    "Riya"
);

Here:

userName

is the key.

And:

Riya

is the stored value.

You can read the value later with:

localStorage.getItem(
    "userName"
);

Why localStorage Is Useful

Websites often need to remember simple browser-side preferences.

Examples include:

  • Dark or light theme
  • Preferred language
  • Dismissed notices
  • Recently viewed products
  • Simple cart data
  • Draft settings
  • Filter choices
  • Sidebar state
  • Tutorial progress
  • Saved UI preferences

The data can survive a page reload.

This makes localStorage useful for small amounts of non-sensitive browser data.

localStorage Is Browser Storage

The data is stored in the user’s browser.

It is not automatically sent to your server.

It also does not automatically sync between:

  • Different browsers
  • Different devices
  • Different user accounts

If a user saves data in Chrome on one computer, that does not mean the same data appears automatically in Firefox or on another device.

For cross-device data, your application normally needs server-side storage tied to a user account.

localStorage Uses Key-Value Pairs

Each item uses:

key → value

Example:

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

Another:

localStorage.setItem(
    "language",
    "en"
);

Now the browser storage contains two separate entries.

You can read either key independently.

Save Data With setItem()

Use:

localStorage.setItem(
    key,
    value
);

Example:

localStorage.setItem(
    "city",
    "Noida"
);

Read it:

console.log(
    localStorage.getItem("city")
);

Output:

Noida

setItem() Replaces an Existing Value

If the key already exists, setItem() replaces its value.

Example:

localStorage.setItem(
    "theme",
    "light"
);

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

Now:

console.log(
    localStorage.getItem("theme")
);

Output:

dark

There is only one value for the key:

theme

Read Data With getItem()

Use:

localStorage.getItem(key);

Example:

const language =
    localStorage.getItem(
        "language"
    );

console.log(language);

If the key exists, you receive its stored string value.

What Happens When a Key Does Not Exist?

If the key is missing:

const value =
    localStorage.getItem(
        "missingKey"
    );

the result is:

null

You can check:

if (value === null) {
    console.log(
        "No saved value"
    );
}

This is different from an empty string.

Remove One Item With removeItem()

Use:

localStorage.removeItem(
    "theme"
);

The key and its value are removed.

Reading it again:

console.log(
    localStorage.getItem("theme")
);

returns:

null

Remove All localStorage Data With clear()

Use:

localStorage.clear();

This removes all localStorage entries for the current origin.

Use it carefully.

If your website stores several unrelated settings, clear() removes all of them.

When you only need to remove one value, prefer:

removeItem()

Get the Number of Stored Items

Use:

localStorage.length

Example:

console.log(
    localStorage.length
);

It returns the number of keys currently stored for that origin.

Read a Key by Position

You can use:

localStorage.key(index);

Example:

const firstKey =
    localStorage.key(0);

console.log(firstKey);

This returns one key name or null when the index does not exist.

Do not depend on key order for important application logic.

localStorage Stores Strings

This is one of the most important rules.

Suppose you write:

localStorage.setItem(
    "quantity",
    5
);

Read it:

const quantity =
    localStorage.getItem(
        "quantity"
    );

console.log(
    typeof quantity
);

Output:

string

The stored value comes back as:

"5"

not the number:

5

Convert Stored Numbers Back to Numbers

Example:

localStorage.setItem(
    "quantity",
    5
);

Read:

const quantity =
    Number(
        localStorage.getItem(
            "quantity"
        )
    );

Now:

console.log(
    typeof quantity
);

Output:

number

Be careful when the key might be missing because:

Number(null)

returns:

0

Check the stored value first when missing data should not become zero.

Safe Number Example

const storedQuantity =
    localStorage.getItem(
        "quantity"
    );

const quantity =
    storedQuantity === null
        ? 1
        : Number(storedQuantity);

Now a missing value uses:

1

instead of silently becoming zero.

What About Booleans?

Suppose:

localStorage.setItem(
    "darkMode",
    true
);

Read it:

const darkMode =
    localStorage.getItem(
        "darkMode"
    );

console.log(darkMode);

Output:

true

But the value is the string:

"true"

not the boolean:

true

Restore a Boolean Correctly

Example:

const darkMode =
    localStorage.getItem(
        "darkMode"
    ) === "true";

Now darkMode is a real boolean.

Another approach is to save booleans through JSON:

localStorage.setItem(
    "darkMode",
    JSON.stringify(true)
);

Then:

const darkMode =
    JSON.parse(
        localStorage.getItem(
            "darkMode"
        )
    );

Use JSON carefully when a key may be missing.

Save an Object in localStorage

You cannot store a JavaScript object directly and expect it to come back as an object.

Suppose:

const user = {
    name: "Riya",
    city: "Delhi"
};

Convert it to JSON:

const userJson =
    JSON.stringify(user);

Save:

localStorage.setItem(
    "user",
    userJson
);

Or in one step:

localStorage.setItem(
    "user",
    JSON.stringify(user)
);

You learned JSON.stringify() in JSON in JavaScript.

Read an Object From localStorage

Get the JSON string:

const storedUser =
    localStorage.getItem(
        "user"
    );

Parse it:

const user =
    JSON.parse(storedUser);

Now:

console.log(user.name);

Output:

Riya

Handle a Missing Object Safely

If:

localStorage.getItem("user")

returns:

null

you should handle that case.

Example:

const storedUser =
    localStorage.getItem(
        "user"
    );

const user =
    storedUser
        ? JSON.parse(storedUser)
        : null;

Now:

user

is either the parsed object or null.

JSON.parse() Can Fail

Stored data may be invalid or changed unexpectedly.

Example:

localStorage.setItem(
    "user",
    "not valid JSON"
);

Then:

JSON.parse(
    localStorage.getItem("user")
);

throws an error.

For important stored JSON, use try...catch.

Safe JSON Reading Function

function getStoredJson(
    key,
    fallback
) {
    const value =
        localStorage.getItem(
            key
        );

    if (value === null) {
        return fallback;
    }

    try {
        return JSON.parse(value);
    } catch (error) {
        console.error(
            `Invalid localStorage data for ${key}`,
            error
        );

        return fallback;
    }
}

Use:

const user =
    getStoredJson(
        "user",
        null
    );

Or:

const cart =
    getStoredJson(
        "cart",
        []
    );

This pattern gives your code a safe fallback.

Save an Array in localStorage

Suppose:

const products = [
    "Laptop",
    "Phone",
    "Tablet"
];

Save:

localStorage.setItem(
    "products",
    JSON.stringify(products)
);

Read:

const storedProducts =
    localStorage.getItem(
        "products"
    );

const products =
    storedProducts
        ? JSON.parse(
            storedProducts
        )
        : [];

Now products is a normal JavaScript array again.

Confirm the Restored Value Is an Array

Use:

if (
    Array.isArray(products)
) {
    console.log(
        "Products restored"
    );
}

When stored data can be changed or corrupted, checking its expected shape is useful.

Review JavaScript Arrays for Array.isArray().

Real Website Example: Save Theme Preference

HTML:

<button id="themeButton">
    Toggle Theme
</button>

JavaScript:

const themeButton =
    document.querySelector(
        "#themeButton"
    );

const savedTheme =
    localStorage.getItem(
        "theme"
    );

if (savedTheme === "dark") {
    document.body.classList.add(
        "dark-theme"
    );
}

themeButton.addEventListener(
    "click",
    () => {
        document.body.classList.toggle(
            "dark-theme"
        );

        const isDark =
            document.body.classList.contains(
                "dark-theme"
            );

        localStorage.setItem(
            "theme",
            isDark
                ? "dark"
                : "light"
        );
    }
);

The user’s choice survives a page reload.

Apply Saved Preferences Early

For visual preferences such as theme, applying the stored choice as early as practical can reduce a flash of the wrong theme.

A production theme system may also respect system preferences and accessibility needs.

The important lesson here is that localStorage can remember a user’s UI choice between page loads.

Real Website Example: Remember a Name

HTML:

<input
    id="name"
    type="text"
    placeholder="Your name"
>

<button id="saveButton">
    Save Name
</button>

<p id="message"></p>

JavaScript:

const nameInput =
    document.querySelector("#name");

const saveButton =
    document.querySelector(
        "#saveButton"
    );

const message =
    document.querySelector(
        "#message"
    );

const savedName =
    localStorage.getItem(
        "name"
    );

if (savedName !== null) {
    nameInput.value =
        savedName;
}

saveButton.addEventListener(
    "click",
    () => {
        const name =
            nameInput.value.trim();

        if (name === "") {
            message.textContent =
                "Enter your name";

            return;
        }

        localStorage.setItem(
            "name",
            name
        );

        message.textContent =
            "Name saved";
    }
);

This is a simple browser preference example.

Do not use this pattern for sensitive personal information without a real privacy and security reason.

Real Website Example: Save Recently Viewed Products

Suppose:

const recentProducts = [
    {
        id: 101,
        name: "Keyboard"
    },
    {
        id: 102,
        name: "Mouse"
    }
];

Save:

localStorage.setItem(
    "recentProducts",
    JSON.stringify(
        recentProducts
    )
);

Read:

const stored =
    localStorage.getItem(
        "recentProducts"
    );

const recentProducts =
    stored
        ? JSON.parse(stored)
        : [];

This is suitable for small, non-sensitive UI history.

Real Website Example: Save a Shopping Cart

A simple cart may look like:

const cart = [
    {
        id: 101,
        name: "Keyboard",
        price: 1500,
        quantity: 2
    },
    {
        id: 102,
        name: "Mouse",
        price: 700,
        quantity: 1
    }
];

Save it:

localStorage.setItem(
    "cart",
    JSON.stringify(cart)
);

Read it:

function getCart() {
    const storedCart =
        localStorage.getItem(
            "cart"
        );

    if (storedCart === null) {
        return [];
    }

    try {
        const cart =
            JSON.parse(
                storedCart
            );

        return Array.isArray(cart)
            ? cart
            : [];
    } catch (error) {
        console.error(
            "Cart data is invalid",
            error
        );

        return [];
    }
}

Now:

const cart =
    getCart();

returns an array.

Create a saveCart() Function

function saveCart(cart) {
    localStorage.setItem(
        "cart",
        JSON.stringify(cart)
    );
}

Use:

const cart =
    getCart();

cart.push({
    id: 103,
    name: "Monitor",
    price: 12000,
    quantity: 1
});

saveCart(cart);

Separating getCart() and saveCart() makes cart storage easier to manage.

Real Website Example: Cart Count

HTML:

<span id="cartCount">0</span>

JavaScript:

const cartCount =
    document.querySelector(
        "#cartCount"
    );

const cart =
    getCart();

cartCount.textContent =
    cart.length;

The cart count now reflects the stored cart after the page reloads.

Save Cart Quantity Instead of Only Item Count

If one product can have a quantity above one, cart.length only counts product rows.

To show total units:

let totalQuantity = 0;

for (const item of cart) {
    totalQuantity +=
        item.quantity;
}

cartCount.textContent =
    totalQuantity;

This combines localStorage with JavaScript loops.

Update an Existing Cart Item

Suppose:

const cart =
    getCart();

Find a product:

const item =
    cart.find(
        (product) =>
            product.id === 101
    );

If it exists:

if (item) {
    item.quantity++;
}

Then save:

saveCart(cart);

Later, you will study array methods such as find() in more depth.

Remove a Product From Stored Cart Data

A common pattern is:

const updatedCart =
    cart.filter(
        (item) =>
            item.id !== 101
    );

saveCart(updatedCart);

This creates a new array without the removed product.

The filter() method will have its own detailed lesson later.

localStorage and Page Reloads

Suppose:

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

Reload the page.

The value can still be read:

console.log(
    localStorage.getItem("theme")
);

Output:

dark

That persistence is the main difference between localStorage and ordinary JavaScript variables.

JavaScript Variables Do Not Survive Reloads

Example:

let theme = "dark";

Reloading the page starts your JavaScript again.

The variable is recreated.

But:

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

stores the value separately in browser storage.

Your script can read it again after reload.

localStorage vs sessionStorage

Both use similar methods:

setItem()
getItem()
removeItem()
clear()

The main practical difference is lifetime.

localStorage persists beyond the current page session.

sessionStorage is tied to the current page session and browser tab context.

You will learn this in the JavaScript sessionStorage tutorial.

localStorage vs Cookies

localStorage and cookies are different browser technologies.

localStorage

  • Accessed through JavaScript
  • Stores strings
  • Not automatically attached to every HTTP request
  • Useful for browser-side preferences and simple data

Cookies

  • Can be sent with matching HTTP requests
  • Have expiration and security attributes
  • Are often used in authentication and server-related workflows
  • Can be restricted with attributes such as HttpOnly, Secure, and SameSite

Do not use localStorage as a drop-in replacement for secure authentication cookies.

localStorage Is Synchronous

Methods such as:

localStorage.getItem()
localStorage.setItem()

run synchronously.

This means JavaScript waits for the operation to finish before continuing.

For small preference values, this is usually manageable.

For large or complex browser storage needs, other APIs such as IndexedDB are more suitable.

Do not use localStorage as a database for large application datasets.

localStorage Storage Limits

Browsers limit how much data an origin can store.

The exact quota can vary by browser, environment, device, privacy mode, and storage policy.

Do not design an application around one fixed quota number.

Treat localStorage as small browser storage rather than large file or database storage.

setItem() Can Fail

Storage can fail.

Possible reasons include:

  • Storage quota limits
  • Browser privacy restrictions
  • Storage being unavailable
  • User or browser settings
  • Environment restrictions

For important writes, you may use try...catch.

Example:

function savePreference(
    key,
    value
) {
    try {
        localStorage.setItem(
            key,
            value
        );

        return true;
    } catch (error) {
        console.error(
            "Preference could not be saved",
            error
        );

        return false;
    }
}

Do not assume storage always succeeds.

localStorage and Private Browsing

Storage behavior can differ in private or restricted browsing modes.

Data may be limited, cleared sooner, or unavailable under some browser policies.

Your application should still work when persistent browser storage is unavailable.

Treat localStorage as an enhancement, not the only place where critical data exists.

localStorage and Origins

Storage is separated by origin.

An origin includes:

  • Protocol
  • Host
  • Port

For example:

https://example.com

and:

https://shop.example.com

are different origins because the host differs.

Their localStorage data is separate.

Similarly:

http://example.com

and:

https://example.com

are different origins because the protocol differs.

The storage Event

The browser can fire a:

storage

event in other same-origin documents when localStorage changes.

Example:

window.addEventListener(
    "storage",
    (event) => {
        console.log(
            event.key,
            event.oldValue,
            event.newValue
        );
    }
);

This can help synchronize simple state between tabs.

Important storage Event Detail

When one page changes localStorage, the storage event is generally delivered to other same-origin browsing contexts, not the same document that performed the change.

If the current page needs to update immediately, update its own state directly when you call setItem().

Use the storage event for communication with other tabs or windows where appropriate.

Real Website Example: Sync Theme Between Tabs

window.addEventListener(
    "storage",
    (event) => {
        if (
            event.key === "theme"
        ) {
            document.body.classList.toggle(
                "dark-theme",
                event.newValue ===
                    "dark"
            );
        }
    }
);

When another same-origin tab changes the stored theme, this tab can update too.

Store a Version With Complex Data

Stored application data can change shape as your code changes.

A useful pattern is:

const settings = {
    version: 1,
    theme: "dark",
    language: "en"
};

Save:

localStorage.setItem(
    "settings",
    JSON.stringify(settings)
);

Later, your code can inspect:

settings.version

and migrate older data if your structure changes.

This matters more in larger applications.

Data Can Become Stale

localStorage persists.

That means old values can remain long after your application changes.

For example:

{
    "currency": "INR"
}

may have been stored months earlier.

Your code should not assume every stored value is still valid forever.

For changing data, consider:

  • A version number
  • A saved timestamp
  • A server refresh
  • A validation step
  • Expiration logic

Add Simple Expiration Logic

localStorage does not provide automatic per-item expiration.

You can store your own expiration time.

Example:

const item = {
    value: "dark",
    expiresAt:
        Date.now() +
        24 * 60 * 60 * 1000
};

localStorage.setItem(
    "themePreference",
    JSON.stringify(item)
);

Read:

const stored =
    localStorage.getItem(
        "themePreference"
    );

if (stored) {
    const item =
        JSON.parse(stored);

    if (
        Date.now() <
        item.expiresAt
    ) {
        console.log(
            item.value
        );
    } else {
        localStorage.removeItem(
            "themePreference"
        );
    }
}

Use expiration only when your product requirement needs it.

localStorage Is Not Secure Storage

Do not store sensitive secrets simply because the browser provides localStorage.

Avoid storing:

  • Passwords
  • Private API keys
  • Server secrets
  • Sensitive financial data
  • Highly sensitive personal records

Data in localStorage is accessible to JavaScript running in that origin.

A cross-site scripting vulnerability can expose stored values to malicious code.

Be Careful With Authentication Tokens

Some applications store tokens in localStorage, but doing so exposes those tokens to JavaScript.

That increases risk if the site has an XSS vulnerability.

Authentication storage is an application-security decision.

Do not choose localStorage automatically for authentication simply because it is easy to use.

Secure cookie-based designs with appropriate attributes are often considered for session authentication, depending on the application architecture.

Authentication deserves a separate security design rather than a one-line storage choice.

JSON Does Not Encrypt localStorage Data

This:

JSON.stringify(user)

only converts data to text.

It does not encrypt or hide it.

Users can inspect browser storage with developer tools.

Do not use JSON serialization as a security measure.

Real Website Example: Save Filter Preferences

Suppose a user selects:

const filters = {
    category: "laptops",
    maxPrice: 50000,
    inStockOnly: true
};

Save:

localStorage.setItem(
    "productFilters",
    JSON.stringify(filters)
);

Read on the next visit:

const storedFilters =
    localStorage.getItem(
        "productFilters"
    );

const filters =
    storedFilters
        ? JSON.parse(
            storedFilters
        )
        : {
            category: "",
            maxPrice: null,
            inStockOnly: false
        };

Now your UI can restore the user’s filter choices.

Real Website Example: Dismiss a Banner

HTML:

<div id="banner">
    <p>Welcome to our new website.</p>

    <button id="closeBanner">
        Close
    </button>
</div>

JavaScript:

const banner =
    document.querySelector(
        "#banner"
    );

const closeBanner =
    document.querySelector(
        "#closeBanner"
    );

const dismissed =
    localStorage.getItem(
        "welcomeBannerDismissed"
    ) === "true";

banner.hidden = dismissed;

closeBanner.addEventListener(
    "click",
    () => {
        banner.hidden = true;

        localStorage.setItem(
            "welcomeBannerDismissed",
            "true"
        );
    }
);

The banner remains dismissed after reload.

Real Website Example: Save a Draft

HTML:

<textarea
    id="draft"
    placeholder="Write your notes"
></textarea>

JavaScript:

const draft =
    document.querySelector("#draft");

const savedDraft =
    localStorage.getItem(
        "draft"
    );

if (savedDraft !== null) {
    draft.value =
        savedDraft;
}

draft.addEventListener(
    "input",
    () => {
        localStorage.setItem(
            "draft",
            draft.value
        );
    }
);

This can preserve a small text draft across reloads.

For large documents or important work, use more robust persistence rather than relying only on localStorage.

Avoid Writing on Every High-Frequency Change Without Thought

The previous draft example writes after every input event.

For a small field, that may be acceptable.

For frequent or larger updates, consider debouncing writes so the browser does not write after every keystroke.

You will learn debouncing later.

Real Website Example: Clear Saved Draft

Add:

<button id="clearDraft">
    Clear Draft
</button>

JavaScript:

const clearDraft =
    document.querySelector(
        "#clearDraft"
    );

clearDraft.addEventListener(
    "click",
    () => {
        draft.value = "";

        localStorage.removeItem(
            "draft"
        );
    }
);

The visible text and stored value are both removed.

Real Website Example: Remember Tutorial Progress

Suppose:

const progress = {
    completedLessons: [
        "variables",
        "data-types",
        "operators"
    ],
    lastLesson: "operators"
};

Save:

localStorage.setItem(
    "javascriptProgress",
    JSON.stringify(progress)
);

Read later and restore the user’s local progress.

For logged-in users who need progress across devices, save it on the server instead.

When Should You Not Use localStorage?

Avoid localStorage when:

  • The data must stay secret
  • The data is large
  • The data needs relational queries
  • The data must sync reliably across devices
  • The data is critical and cannot be lost
  • The server must be the source of truth
  • You need secure authentication storage without a full security design
  • You need large offline datasets

Other storage options may include:

  • Server databases
  • IndexedDB
  • Cookies
  • Cache APIs
  • File storage
  • In-memory state

Choose storage based on the actual requirement.

localStorage vs IndexedDB

localStorage is simple but synchronous and string-based.

IndexedDB supports larger and more structured browser-side data and works asynchronously.

Use localStorage for small settings and lightweight state.

Consider IndexedDB when your browser application needs larger datasets, offline records, or more capable storage.

Common Beginner Mistakes

Forgetting localStorage Stores Strings

This:

localStorage.setItem(
    "quantity",
    5
);

comes back as:

"5"

Convert it when you need a number.

Saving an Object Without JSON.stringify()

Wrong:

localStorage.setItem(
    "user",
    {
        name: "Riya"
    }
);

The object is converted to a string that is not useful JSON.

Use:

localStorage.setItem(
    "user",
    JSON.stringify({
        name: "Riya"
    })
);

Forgetting JSON.parse()

This:

const user =
    localStorage.getItem(
        "user"
    );

returns a string.

Parse JSON when the stored value represents an object or array.

Parsing a Missing Key Without Planning for It

Check for:

null

before assuming stored data exists.

Assuming Stored JSON Is Always Valid

Data may be corrupted, manually changed, or left from an older version of your application.

Use try...catch where invalid JSON is possible.

Using clear() When removeItem() Is Enough

clear() removes every localStorage entry for the origin.

Use:

removeItem()

for one key.

Storing Sensitive Secrets

Do not store passwords, private API keys, or server secrets in localStorage.

Treating localStorage as a Database

It is not designed for large application datasets or complex data access.

Depending on One Fixed Storage Limit

Browser quotas vary.

Do not assume one exact number applies everywhere.

Assuming localStorage Always Works

Browser settings and privacy modes can restrict storage.

Important applications need graceful fallback behavior.

Forgetting Data Can Become Old

Persistent data can become stale.

Validate, version, refresh, or expire it when your application requires that.

Expecting localStorage to Sync Across Devices

It is browser-side origin storage.

Use a backend for cross-device user data.

Confusing localStorage With Cookies

localStorage data is not automatically sent with every HTTP request.

Cookies follow different browser and HTTP rules.

Assuming JSON.stringify() Encrypts Data

It does not.

It only serializes the value.

Using localStorage for Authentication Without Security Planning

Token and session storage affects application security.

Do not choose a storage mechanism solely for convenience.

Best Practices for JavaScript localStorage

Use clear and consistent key names.

Example:

theme
cart
productFilters
javascriptProgress

Store only data that genuinely needs browser persistence.

Use JSON.stringify() for objects and arrays.

Use JSON.parse() with safe fallback handling.

Check the expected data type after parsing important stored values.

Use removeItem() when deleting one key.

Use clear() only when you truly intend to remove all origin storage.

Handle storage failures when saving important preferences.

Do not store private secrets.

Treat persistent browser data as potentially stale.

Version complex stored structures when your application may change them later.

Use server storage when data must follow a user across devices.

Use IndexedDB for larger or more capable client-side persistence.

Beginner Exercise

Save these values in localStorage:

const userName = "Amit";
const theme = "dark";
const quantity = 3;

Complete these tasks:

  1. Save userName.
  2. Save theme.
  3. Save quantity.
  4. Reload the page.
  5. Read all three values.
  6. Convert quantity back into a number.
  7. Remove the theme.
  8. Check that reading the removed theme returns null.

Then print:

localStorage.length

to see how many keys remain.

Challenge Exercise

Create:

const cart = [
    {
        id: 1,
        name: "Keyboard",
        price: 1500,
        quantity: 2
    },
    {
        id: 2,
        name: "Mouse",
        price: 700,
        quantity: 1
    }
];

Complete these tasks:

  1. Save the cart with JSON.stringify().
  2. Reload the page.
  3. Read the cart.
  4. Parse it with JSON.parse().
  5. Confirm it is an array.
  6. Calculate the total cart value.
  7. Add one more item.
  8. Save the updated cart again.
  9. Remove the entire cart with removeItem().

Extra Challenge

Create this HTML:

<button id="themeButton">
    Toggle Theme
</button>

<p id="status"></p>

Build a theme preference that:

  1. Reads the saved theme when the page loads.
  2. Adds a dark-theme class when needed.
  3. Toggles the class on button click.
  4. Saves the new choice in localStorage.
  5. Shows the current theme inside #status.
  6. Still works after a page reload.

Frequently Asked Questions

What is localStorage in JavaScript?

localStorage is browser storage that keeps string key-value pairs for an origin and can persist beyond page reloads and browser sessions.

How do I save data in localStorage?

Use:

localStorage.setItem(
    "key",
    "value"
);

How do I read localStorage data?

Use:

localStorage.getItem(
    "key"
);

What does getItem() return when a key is missing?

It returns:

null

How do I remove one localStorage item?

Use:

localStorage.removeItem(
    "key"
);

How do I remove all localStorage data?

Use:

localStorage.clear();

This removes every localStorage entry for the current origin.

Does localStorage survive a page reload?

Yes.

That is one of its main uses.

Does localStorage remain after the browser closes?

Normally, localStorage is designed to persist beyond the current browser session.

Browser privacy settings, private modes, user actions, or storage policies can change actual persistence.

Does localStorage expire automatically?

No automatic per-item expiration is built into the basic localStorage API.

If you need expiration, store your own timestamp or use another storage design.

Can localStorage store objects?

It stores strings.

Convert objects first:

localStorage.setItem(
    "user",
    JSON.stringify(user)
);

Read:

const user =
    JSON.parse(
        localStorage.getItem(
            "user"
        )
    );

Handle missing or invalid values safely.

Can localStorage store arrays?

Yes, after converting them to JSON strings.

localStorage.setItem(
    "items",
    JSON.stringify(items)
);

Can localStorage store numbers?

It stores them as strings.

Convert the returned value when you need a number.

Can localStorage store booleans?

They are stored as strings unless you serialize them.

Convert the value back into a boolean when reading it.

Is localStorage synchronous?

Yes.

Its main methods run synchronously.

How much data can localStorage hold?

Browser storage quotas vary by browser, environment, and policy.

Do not rely on one fixed limit.

Use it for small amounts of data.

Is localStorage secure?

It is not secure storage for secrets.

JavaScript running in the same origin can access it.

Security issues such as XSS can expose stored values.

Should I store passwords in localStorage?

No.

Passwords should not be stored there.

Should I store API keys in localStorage?

Do not store private server API keys or secrets in browser storage.

Anything available to frontend JavaScript can be inspected by users or malicious script running in the origin.

Should I store authentication tokens in localStorage?

That is an application-security decision, not a default recommendation.

Values in localStorage are accessible to JavaScript, which matters if an XSS vulnerability exists.

Choose authentication storage as part of a complete security architecture.

Is JSON.stringify() encryption?

No.

It only converts JavaScript data into JSON text.

What is the difference between localStorage and sessionStorage?

localStorage persists beyond the current page session.

sessionStorage is tied to the current page session and tab context.

What is the difference between localStorage and cookies?

Cookies can participate in HTTP requests and support security attributes.

localStorage is JavaScript-accessible browser storage and is not automatically sent with requests.

Does localStorage work across different domains?

No.

Storage is separated by origin.

Does localStorage sync across browser tabs?

Same-origin tabs can access the same localStorage area.

The storage event can notify other same-origin documents when values change.

Does the storage event fire in the same tab that changed the value?

It is generally used to notify other same-origin browsing contexts rather than the document that performed the change.

Update the current document directly when you call setItem().

Can localStorage fail?

Yes.

Storage restrictions, privacy settings, quota limits, or browser policies can make a write fail.

When should I use IndexedDB instead?

Consider IndexedDB when you need larger datasets, structured offline storage, or more capable asynchronous client-side persistence.

What should I learn after localStorage?

Learn JavaScript sessionStorage next. It uses a similar API but keeps data for the current page session instead of long-term browser persistence.

Summary

JavaScript localStorage saves string key-value pairs in the browser.

The four main methods are:

localStorage.setItem()
localStorage.getItem()
localStorage.removeItem()
localStorage.clear()

Save:

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

Read:

const theme =
    localStorage.getItem(
        "theme"
    );

For objects and arrays, use:

JSON.stringify()

before saving and:

JSON.parse()

after reading.

You also learned how to:

  • Save strings
  • Restore numbers and booleans
  • Save objects and arrays
  • Handle missing keys
  • Handle invalid JSON
  • Save theme preferences
  • Save simple cart data
  • Save filters and drafts
  • Remove saved values
  • Use the storage event
  • Add custom expiration logic
  • Understand origin boundaries
  • Handle possible storage failures
  • Avoid sensitive data
  • Understand why localStorage is not a database
  • Know when server storage or IndexedDB is a better choice

localStorage is useful for small browser-side preferences and simple persistent state when the data does not need to be secret.

Continue Learning JavaScript

Previous Lesson: JavaScript Fetch API Explained

Course Home: JavaScript Tutorial for Beginners

Next Lesson: JavaScript sessionStorage Explained

In the next lesson, you will learn how sessionStorage uses the same key-value methods while keeping data within the current page session and tab context.

James Parker

James Parker

James Parker is a technology writer and WordPress enthusiast who shares practical guides on SEO, web development, AI tools, and digital growth. He focuses on creating easy-to-follow tutorials that help beginners and professionals build better websites and improve their online presence.