sessionStorage in JavaScript: data that lives for one tab

sessionStorage keeps strings for one tab: they survive a reload and vanish when the tab closes, and a second tab starts empty. That is exactly right for a draft or a step in a form, and wrong for anything that should still be there tomorrow or for anyone else.

sessionStorage in JavaScript is the same key-value store as localStorage with one difference: its life is a single tab. Values survive a reload and are gone when the tab closes; a second tab on the same page starts with its own empty store.

The markup. The highlighted line is the part this term is about.
The markup. The highlighted line is the part this term is about.

That scope is right for a draft the reader is typing, a step in a multi-page form, or a filter they set for this visit, and wrong for a preference that should be there tomorrow or for anything another person needs to see.

This guide covers the difference precisely, when per-tab is the right scope, the same throwing behaviour as localStorage, and what to use for shared data.

<script>
  sessionStorage.setItem('step', '2');
  var step = sessionStorage.getItem('step');
  sessionStorage.removeItem('step');
</script>

Identical API to localStorage. The difference is how long it lives and who can see it.

sessionStorage versus localStorage, precisely

sessionStorage localStorage
Survives a reload Yes Yes
Survives navigating within the tab Yes Yes
Survives closing the tab No Yes
Visible to another tab on the same site No Yes
Copied when the tab is duplicated A snapshot, then independent Shared
sessionStorage is localStorage with a shorter life: kept across reloads, gone when the tab closes, separate per tab. Right for a draft or a wizard step; wrong for anything that should still be there tomorrow or for anyone else.
sessionStorage is localStorage with a shorter life: kept across reloads, gone when the tab closes, separate per tab. Right for a draft or a wizard step; wrong for anything that should still be there tomorrow or for anyone else.

The row that decides most choices is the fourth. Two tabs of the same page have separate sessionStorage and shared localStorage.

A copy per person ✗ Each edit lives on one machine ✗ No way to merge the changes ✗ Nobody can say which is current ✗ The oldest copy keeps circulating One address ✓ Everyone opens the same page ✓ A correction is seen by all ✓ There is only one current version ✓ Forwarding shares the page, not a copy
Anything kept in a browser's storage is one copy per reader. Anything two readers must share lives at one address.

When per-tab is the right scope

Progress through a multi-step form

<script>
  function saveStep(n, data) {
    try {
      sessionStorage.setItem('form', JSON.stringify({ step: n, data: data }));
    } catch (e) {}
  }
</script>

If someone opens the same form in two tabs to compare two cases, localStorage would have the two overwrite each other. sessionStorage keeps them apart, which is what the reader expects.

A filter or sort set for this visit

A reader who sorted a table by date probably wants that for now, not permanently. sessionStorage remembers it through a reload and forgets it afterwards, which matches the intent better than a preference that persists for a year.

A scroll position across navigation

<script>
  addEventListener('beforeunload', function () {
    try { sessionStorage.setItem('y', String(scrollY)); } catch (e) {}
  });
  addEventListener('load', function () {
    var y = sessionStorage.getItem('y');
    if (y) scrollTo(0, Number(y));
  });
</script>

Anything that should not leak between tabs

Two calculators open with different scenarios. Two drafts of the same document. Anything where "the other tab changed my values" would be a bug.

When localStorage is right instead

  • A theme preference. Should apply everywhere and persist.
  • A dismissed banner. Dismissing in one tab should dismiss in all.
  • A saved draft. Should survive a browser crash, which sessionStorage will not.

Rule of thumb: preferences go in localStorage, in-progress state goes in sessionStorage.

Same guards required

<script>
  try { sessionStorage.setItem(k, v); } catch (e) {}
</script>

Identical failure modes: it throws in private browsing modes and inside sandboxed frames with no origin. Unguarded, the exception stops the rest of your script.

Same string-only constraint, too — serialise objects with JSON.stringify.

Neither is shared between people

Worth restating because it is the mistake that costs real time. Both are per browser, per machine. Neither can hold state that two people need to see.

Nothing in a standalone file can. That requires the document to live at one address — which is the difference between a file everybody has a copy of and a page everybody opens.

Which one, by requirement

You want it to sessionStorage localStorage
Survive a reload Yes Yes
Survive closing the tab No Yes
Be shared between two tabs No Yes
Be independent per tab Yes No
Survive a browser crash No Yes
Be forgotten automatically Yes No

The two bold rows are the only reasons to choose it, and they are good reasons — a form open twice, two calculator scenarios, a filter that should not become permanent.

The failure worth predicting

<script>
  // wrong: two tabs of the same form overwrite each other
  localStorage.setItem('form', JSON.stringify(data));

  // right: each tab keeps its own progress
  try { sessionStorage.setItem('form', JSON.stringify(data)); } catch (e) {}
</script>

A reader comparing two cases side by side is a normal thing to do, and with the wrong storage the two sets of answers merge into one. The symptom is a user reporting that "the form changed by itself", which is very hard to reproduce unless you know to open two tabs.

Both APIs need the same guard for the same reasons — see localStorage. And neither can hold anything two people share; that needs a document at one address.

Where session storage is the right tool

A form that spans three pages, with the answers kept until the last page submits. A search filter the reader set for this visit and would be surprised to find still set next week.

A "you have unsaved changes" draft that should survive an accidental reload and no more. In each case the value belongs to this visit, and leaving it behind would be the bug.

Duplicated tabs

One exception to "separate per tab": when a reader duplicates a tab, most browsers copy the session storage into the new one at that moment. From then on the two are independent.

A page that assumes a value is unique to one tab can be surprised by the copy, which matters for anything that acts like a lock or a step counter.

Using sessionStorage: 4 steps

  1. Ask how long the value should live. This tab only: session. Until cleared: local. Beyond this person: neither; a shared page at one address.
  2. Wrap the calls in try, as with localStorage. The same failures in private mode and inside sandboxed frames.
  3. Save on input, restore on load. For a draft, write on every keystroke and read it back when the page opens, so a reload loses nothing.
  4. Tell the reader what happens when they close the tab. One line near the form. A lost draft with no warning is the worst outcome, and it is the one this store produces by design.

Questions people ask

How is sessionStorage different from localStorage?

Scope. sessionStorage belongs to one tab and is cleared when the tab closes. localStorage is shared across tabs on the same origin and persists.

Does a page reload clear it?

No. Reloading, and navigating within the tab, keep it. Only closing the tab clears it.

What happens if I duplicate the tab?

The copy starts with a snapshot of the current contents, and the two then diverge independently.

What is it best for?

Anything that should not leak between tabs — multi-step form progress, a scroll position, a filter the reader set for this visit only.

Keep reading