# Remembering Data with localStorage

Make a page remember things between visits with localStorage, save whole lists with JSON, start cleanly when nothing is saved yet, and know what sessionStorage and cookies are for and what must never be stored in the browser.

Apprentice · JavaScript · Web Development · Updated November 1, 2026

## After this lesson you can

- Save, read and remove a value in the browser with localStorage.setItem, getItem and removeItem
- Save an array in localStorage with JSON.stringify, load it with JSON.parse, and start with an empty list when nothing is saved yet
- Choose between localStorage, sessionStorage and a cookie, and keep passwords and private data out of the browser's storage

## Key takeaways

- localStorage keeps text under a key for your site, even after the browser closes. setItem saves, getItem reads, and removeItem deletes.
- localStorage stores only strings. Turn an array or object into text with JSON.stringify before saving, and back with JSON.parse after loading.
- getItem gives null when nothing is saved under that key yet, so start with an empty list in that case.
- sessionStorage works the same way but forgets when the tab closes. Cookies are small pieces of text the browser sends to the server with every request.
- Never store passwords, card numbers or anything private in the browser. Any script on the page, and anyone at that computer, can read it.

Add five books to the Reading List, press **F5** to reload, and they're gone. A web page forgets everything when it reloads: every variable starts over. Yet plenty of sites remember you: the dark mode you picked last week, a game's high score, the playlist you were halfway through. Many of them do it with **localStorage**, a small store the browser keeps for each site. This lesson makes the Reading List remember its books between visits, and shows what you should never keep there.

## A notebook the browser keeps for your site

Think of a locker at the gym: you put your things in under your locker number, and they're still there next time. The browser gives every site a small store like that, called **localStorage**. Each thing in it is saved under a **key**, a name you choose, and you get it back by the same key. It stays after the tab closes, after the browser closes, and after the computer restarts, until your code (or the person) removes it. (Safari is the exception: it clears a site's localStorage after seven days of use with no visit to that site.)

Three methods do the work:

```javascript
localStorage.setItem("readerName", "Maya");
console.log(localStorage.getItem("readerName"));

localStorage.removeItem("readerName");
console.log(localStorage.getItem("readerName"));
```

- `setItem(key, value)` saves the value under the key, replacing anything already there.
- `getItem(key)` reads it back: here the Console shows `Maya`.
- `removeItem(key)` deletes it. After that, `getItem` gives `null`: nothing is saved under that key.

Each site has its own store: a page on another site can't read yours. To see what's saved, open the developer tools (**F12**), choose **Application** (in Chrome and Edge) or **Storage** (in Firefox), then **Local storage** and your page's address. You can edit or delete entries there too.

## Everything is stored as text

localStorage keeps **strings** only. Give `setItem` anything else and it turns it into text first, the way `String()` does. For a number that's mostly fine: save `320`, and you get back `"320"`, which needs `Number()` again. For a list it's a disaster:

```javascript
const books = [{ title: "Dune", pages: 412 }];

console.log(String(books));
console.log(String(["Dune", "Emma"]));
console.log(String(320));
```

```text
[object Object]
Dune,Emma
320
```

Save an array of books as it is, and what lands in storage is the text `[object Object]`: the books themselves are lost. The list of titles comes out as `Dune,Emma`, which can't be turned back into a list safely, since a title can have a comma in it.

## Saving a list with JSON

You met the fix in *JSON: Data You Can Save and Send*. `JSON.stringify` turns an array or object into text that keeps all of it, and `JSON.parse` turns that text back into a real array or object:

```javascript
const books = [
  { title: "Dune", pages: 412, status: "reading" },
  { title: "Emma", pages: 474, status: "want-to-read" },
];

const text = JSON.stringify(books);
console.log(text);

const loaded = JSON.parse(text);
console.log(loaded.length);
console.log(loaded[1].title);
```

```text
[{"title":"Dune","pages":412,"status":"reading"},{"title":"Emma","pages":474,"status":"want-to-read"}]
2
Emma
```

So the page saves with `JSON.stringify` and loads with `JSON.parse`, and keeps the key in one constant so it's spelled the same both times:

```javascript
const storageKey = "reading-list";

function saveBooks(books) {
  localStorage.setItem(storageKey, JSON.stringify(books));
}

function loadBooks() {
  return JSON.parse(localStorage.getItem(storageKey));
}
```

Call `saveBooks(books)` after every change: a book added, a status changed, a book removed. Call `loadBooks()` once, when the page starts. That `loadBooks` has a problem, though, on someone's very first visit.

## When nothing is saved yet

The first time anyone opens the page, nothing is saved under `"reading-list"`, so `getItem` gives `null`. And `JSON.parse(null)` doesn't fail. It quietly gives back `null`, which you can see in Node with the value `getItem` would give:

```javascript
const saved = null;

console.log(JSON.parse(saved));

const books = JSON.parse(saved) ?? [];
console.log(books.length);
```

```text
null
0
```

Without the fix, the page's first `books.push(...)` stops with *TypeError: Cannot read properties of null (reading 'push')*. With `?? []` (read "nullish coalescing", or "double question mark"), from *Missing Values: null, undefined, ?. and ??*, a first visit starts with an empty list.

One more thing can go wrong: the saved text can be broken, for example after someone edits it by hand in the developer tools. `JSON.parse` throws an error on text that isn't JSON, so a careful page catches it, with the `try` and `catch` from *Handling Errors with try, catch and finally*:

```javascript
function booksFrom(saved) {
  if (saved === null) {
    return [];
  }
  try {
    return JSON.parse(saved);
  } catch (error) {
    return [];
  }
}

console.log(booksFrom(null));
console.log(booksFrom('[{"title":"Dune"}]'));
console.log(booksFrom("[{title:Dune}"));
```

```text
[]
[ { title: 'Dune' } ]
[]
```

**Try it.** In your `reading-list` page's `app.js`, save a small array of two books with `localStorage.setItem` and `JSON.stringify`. Find it in the developer tools' **Application** (or **Storage**) tab, then reload the page and read it back in the Console with `JSON.parse(localStorage.getItem("reading-list"))`. Last, delete the entry in the developer tools and run the same line again: `null`.

## sessionStorage and cookies

**sessionStorage** has exactly the same methods as localStorage, `setItem`, `getItem` and `removeItem`, but it's tied to one tab: it survives a reload, and it's gone when the tab closes. It suits things that belong to one sitting, such as the answers to a long form someone is halfway through, or a game round in progress.

**Cookies** are older and different. A cookie is a small piece of text that the browser sends back to the server with every request to that site. That's what makes them useful for staying signed in: the server sets a cookie when you sign in, and every page you open after that carries it, so the server knows it's you. Servers usually set and read them, and page code rarely needs to touch them, which is why this course doesn't.

| | Keeps it until… | Sent to the server? | Good for |
|---|---|---|---|
| localStorage | your code or the person removes it, or, in Safari, after seven days with no visit | no | a reading list, settings, favorites, a high score |
| sessionStorage | the tab closes | no | a half-filled form, a game round |
| Cookie | the date the server gives it | yes, with every request | staying signed in |

## What never to store

localStorage isn't locked. Any JavaScript running on your page can read every key in it, including code from another site that the page loads, and anyone sitting at that computer can open the developer tools and read it. It isn't encrypted either. So:

- **Never** store passwords, credit card numbers, or private details such as a home address or health information.
- **Do** store things that would be fine on a sticky note on the person's own screen: their reading list, their dark-mode choice, which photos they marked as favorites.

There's a size limit too, about 5 MB per site in most browsers: plenty for text, too little for photos.

## Check yourself

2 questions to try on the lesson page.

## So what

With `JSON.stringify`, `JSON.parse` and a sensible empty start, any page can remember a person's things between visits, with no server and no account. Settings, favorites, high scores and drafts are all built this way.

## Key terms

- [Local Storage](https://www.ask-codey.com/glossary/local-storage)
- [Session Storage](https://www.ask-codey.com/glossary/session-storage)
- [JSON.stringify()](https://www.ask-codey.com/glossary/json-stringify)
- [JSON.parse()](https://www.ask-codey.com/glossary/json-parse)
- [Cookie](https://www.ask-codey.com/glossary/cookie)

## Cheat sheets

- [Remembering Data with localStorage](https://www.ask-codey.com/cheat-sheets/javascript-storage-local-and-session-cheat-sheet)

## Related

- [JSON: Data You Can Save and Send](https://www.ask-codey.com/lessons/javascript-json-stringify-and-parse)
- [Missing Values: null, undefined, ?. and ??](https://www.ask-codey.com/lessons/javascript-tricky-values-null-and-undefined)

Source: https://www.ask-codey.com/lessons/javascript-storage-local-and-session
