Skip to content
Bugwise
Menu
Web Testing

Cookies, Sessions and Storage

How websites remember you with cookies, sessions, localStorage and sessionStorage, what consent banners must really do, and how to test login state, expiry, carts and privacy with DevTools.

35 min intermediate Web

A customer checks their bank balance on a library computer, clicks Log out and walks away. The next person opens the same browser, presses Back, then Reload… and lands in the first customer’s account.

The logout button “worked”: it showed the login page. But the login token was still sitting in the browser’s storage, and the app happily used it again. Nobody noticed in testing, because nobody looked at what the browser was remembering.

That’s what this lesson is about. Websites keep a surprising amount of data in your browser: cookiesCookieA small piece of data a website stores in your browser, for example to keep you logged in.Open in glossary →, local storageLocal storageBrowser storage where websites keep data that survives closing the tab, like settings or a cart.Open in glossary →, session storage and more. Testers who know where to look find bugs in privacy, security and “it forgot my cart” problems that everyone else misses.

Why it matters

  • Security: a session that doesn’t end on logout, or a token readable by any script, can hand someone else your account.
  • Privacy and law: in the EU and UK, tracking cookies need consent. A “Reject” button that doesn’t actually reject is a legal risk, not just a bug.
  • Money: a cart that disappears after login, or a checkout that logs you out halfway, loses sales.
  • Trust: seeing someone else’s cart or name on a shared computer is the kind of bug that ends up in the news.

Where a website keeps data

StorageLifetimeSent to the server automatically?Readable by page JavaScript?Typical use
CookieUntil it expires, or until the browser closes (session cookie)Yes, with every request to its domainYes, unless HttpOnlyLogin session, consent choice, language, analytics IDs
localStorageForever, until the site or user deletes itNoYesGuest cart, theme, “don’t show again” flags
sessionStorageUntil the tab is closed (survives reloads)NoYesForm drafts, one-time banners, checkout steps in one tab
IndexedDBForever, until deletedNoYesLarge structured data: offline mode, cached messages, files
Cache Storage / HTTP cacheUntil evicted or cleared(It replaces requests)Cache Storage: yesOffline pages (service workers), images, scripts

The sizes differ too: a cookie holds about 4 KB, localStorage and sessionStorage about 5 MB per site, and IndexedDB can hold far more. You don’t need to memorize numbers, but you should know which one a feature uses, because that decides what survives a reload, a closed tab or a logout.

Cookies up close

A server creates a cookie by sending a Set-Cookie header in its response. The browser stores it and sends it back in a Cookie header with every following request to that site.

Response header from the server

Set-Cookie: session_id=s_9f2c41e7; Domain=shop.example; Path=/; Max-Age=2592000; HttpOnly; Secure; SameSite=Lax

Name=value the data itself

Domain, Path where it’s sent

Expires / Max-Age how long it lives

HttpOnly, Secure, SameSite security flags

AttributeWhat it doesWhat to check
Name / ValueThe data, e.g. session_id=s_9f2c…No readable personal data (email, name) or secrets in plain text
DomainWhich hosts receive it. Domain=shop.example also includes subdomains like api.shop.example; without a Domain, only the exact host gets itNot wider than needed
PathWhich URLs receive it, usually /Admin cookies limited to admin paths if intended
Expires / Max-AgeWhen it’s deleted. No expiry = session cookieMatches the requirement (“Remember me” for 30 days, otherwise session)
HttpOnlyPage JavaScript can’t read it (document.cookie won’t show it)Must be set on session/auth cookies, so Cross-site scripting (XSS)Cross-site scripting (XSS)An attack where text a user enters is run as code in other people's browsers.Open in glossary → can’t steal them
SecureOnly sent over HTTPSHTTPSThe secure version of HTTP; traffic between the browser or app and the server is encrypted.Open in glossary →Must be set on anything sensitive
SameSiteWhether it’s sent on requests coming from other sites: Strict, Lax or NoneLax or Strict for sessions. None requires Secure. If SameSite is missing, Chromium browsers (Chrome, Edge) treat the cookie as Lax

Session cookies vs persistent cookies

  • A session cookie has no Expires or Max-Age. The browser deletes it when it closes. In DevTools its expiry shows as Session.
  • A persistent cookie has an expiry date and survives restarts. “Remember me”, language and consent cookies are usually persistent. Chrome caps cookie lifetimes at 400 days.

First-party vs third-party cookies

  • First-party: set by the site in the address bar (shop.example). Login, cart and consent cookies.
  • Third-party: set by another domain embedded in the page, e.g. an ad network’s IDE cookie from adnet.example. Used mostly for tracking across sites.

Browsers increasingly restrict third-party cookies. Safari blocks them by default, Firefox isolates them per site, and Chrome blocks them in Incognito windows and lets users block them everywhere. For testers this means: features that rely on third-party cookies (embedded logins, chat widgets, payment iframes) must be tested in Safari, Firefox and Incognito, or they’ll break for real users. See Cross-browser Testing.

Sessions: how “staying logged in” works

HTTP itself has no memory. Every request is a stranger. A sessionSessionThe period during which a user stays logged in without entering their credentials again.Open in glossary → is how the server recognizes you again:

  1. You log in. The server checks your password and creates a session record: “session s_9f2c belongs to Anna, last active 09:00”.
  2. The server sends a session tokenSession tokenA string the server issues after login that proves who you are on later requests.Open in glossary → in a Set-Cookie header. The token is just a long random ID, not your password.
  3. The browser sends the cookie with every request. The server looks up the session and knows it’s Anna.
  4. The session expires after a period of inactivity (an idle timeout, e.g. 30 minutes for a bank) and/or a maximum age (an absolute timeout, e.g. 12 hours). The server must reject the old token afterwards.
  5. Logout destroys the session on the server and tells the browser to delete the cookie. Even a copied token should stop working.

Some apps use a token (often a JWT) stored in localStorage instead of a cookie and send it in an Authorization header. That works, but any script on the page, including an injected one, can read localStorage. So check extra carefully that the token is removed on logout and expires on its own.

“Remember me” usually means a persistent cookie with a long expiry (for example 30 days) instead of a session cookie. When it’s unchecked, closing the browser should log you out.

localStorage, sessionStorage, IndexedDB and cache

EventCookies (session)Cookies (persistent)localStoragesessionStorage
Reload the pageKeptKeptKeptKept
Open the site in a new tabSharedSharedSharedNew, empty
Close and reopen the tabKeptKeptKeptGone
Quit and reopen the browserGoneKept until expiryKeptGone
Private / Incognito windowSeparate, wiped on closeSeparate, wiped on closeSeparate, wiped on closeSeparate
DevTools › Clear site dataGoneGoneGoneGone
User clicks Log outOnly what the app deletesOnly what the app deletesOnly what the app deletesOnly what the app deletes

(Reopening a closed tab with Ctrl/Cmd+Shift+T, or duplicating a tab, can bring sessionStorage back, so close tabs normally when you test this.)

The last row is the important one. Logout clears nothing automatically. The app must delete every piece of personal data itself. That’s where the bugs are.

IndexedDB is a real database inside the browser, used by apps that work offline (email, notes, chat). Test it like localStorage: is it cleared on logout? Does it hold sensitive data? Cache Storage (used by service workers) can serve an old version of a page after a release, a classic “the fix doesn’t show up” problem. Clear site data removes all of these at once.

In the EU, the ePrivacy rules require consent before storing non-essential cookies (analytics, advertising, social media), and the GDPR defines what valid consent is. The UK has similar rules (PECR), and since 2026 allows some simple first-party analytics cookies without consent as long as users can opt out, so check which rules your product follows. You don’t need to be a lawyer, but you should test these points:

  • Nothing optional before a choice. Before you click anything, only strictly necessary cookies may exist (session, cart, security, the consent choice itself). No _ga, no ad cookies, no requests to analytics domains.
  • Reject is as easy as Accept. A “Reject all” button on the first layer, equally visible. Not hidden behind “Settings” in grey text.
  • Reject really rejects. After rejecting, no analytics cookies appear, and no analytics requests show up in the Network panel, on this page or the next ones.
  • Accept really accepts. The expected cookies appear, and only after the click.
  • The choice is remembered (usually in a consent cookie), and the banner doesn’t reappear on every page.
  • Consent can be withdrawn as easily as it was given (a “Cookie settings” link), and withdrawing deletes the cookies or at least stops new tracking.
  • Granular choices work. If there are toggles per category, each one is respected.

Try it: a shop and its Application panel

Pantry is a small shop with DevTools’ Application panel next to it. Everything you do writes to cookies, localStorage or sessionStorage, and changed rows flash yellow. Use the browser controls to close the tab, quit the browser or let time pass.

pantry.example
Free delivery on orders over €40
Pantry
Guest 0

Log in

Test accounts, password pre-filled.

  • Olive oil, 750 ml€8.90
  • Coffee beans, 1 kg€11.50
  • Fusilli pasta, 500 g€1.80

Your cart

Empty

DevTools›Application
https://pantry.example

No cookies for this site.

Select a row to see its full value.

Browser controls

Tue 13 Oct, 09:00

  • → Page loaded. No cookies yet: the consent banner is waiting for your choice.

How to inspect and edit storage in real DevTools

New to DevTools? Start with DevTools for Testers.

  1. Open DevTools (F12 / Cmd+Option+I) and go to the Application panel.
  2. In the sidebar under Storage, expand Cookies, Local storage or Session storage and click the site’s origin.
  3. Read the table: name, value, domain, path, Expires / Max-Age, size, HttpOnly, Secure, SameSite. Cookies with problems are highlighted, and hovering shows why.
  4. Edit a value by double-clicking it. Delete a row by selecting it and pressing Delete, or use the 🚫 button to clear the whole list.
  5. Clear everything: Application › Storage › Clear site data.
  6. To see which cookies a request sent or received, open the request in Network and check its Cookies tab. Blocked cookies are shown with the reason.
  1. Open DevTools (F12) and go to the Storage panel.
  2. Expand Cookies, Local Storage, Session Storage, Indexed DB or Cache Storage and pick the site.
  3. Double-click a value to edit it. Right-click a row to delete it, or delete everything for the site.
  4. The sidebar on the right parses values, which is handy for JSON in localStorage.
  1. Enable developer features (Safari › Settings › Advanced › Show features for web developers) and open Web Inspector with Cmd+Option+I.
  2. Open the Storage tab and choose Cookies, Local Storage, Session Storage or IndexedDB.
  3. Double-click values to edit, and use the delete key or the trash button to remove entries.
  4. Remember that Safari blocks third-party cookies and limits some script-written storage, so features can behave differently than in Chrome.

The Console is useful too:

  • document.cookie lists the cookies JavaScript can read. If you see the session cookie here, it’s missing HttpOnly. That’s a bug.
  • localStorage.getItem('cart') shows one value. Object.keys(localStorage) lists every key.
  • localStorage.clear() and sessionStorage.clear() wipe them for this site.

What to test

Login and logout

  • Logging in sets a session cookie with HttpOnly, Secure and SameSite. Nothing secret appears in localStorage or the URL.
  • Logging out deletes the session cookie and any tokens or personal data in localStorage, sessionStorage and IndexedDB.
  • After logout, Back and Reload don’t show account pages. A copied old session cookie no longer works.

Session expiry and “Remember me”

  • After the idle timeout, the next action asks you to log in again, with a clear message and without losing what you typed if possible.
  • “Remember me” off: quitting the browser logs you out (session cookie). “Remember me” on: you stay logged in until the stated expiry, then you’re logged out.
  • The session also expires on the server: deleting or editing the cookie mid-session leads to a clean “Please log in” state, not a crash or a blank page.

Multiple tabs and windows

  • Logging out in one tab logs you out in others on their next action.
  • Logging in as another user in a second tab doesn’t mix data between the two.
  • A private / Incognito window starts clean and keeps nothing after closing.

Cart and preferences

  • The guest cart survives a reload and a browser restart (if the requirement says so).
  • Logging in merges or replaces the guest cart as specified. Logging out doesn’t leave the cart for the next person on the same browser.
  • Language, theme and “don’t show again” choices persist where expected, and nowhere else.

Consent and privacy

  • No optional cookies or analytics requests before consent. Reject works. Accept works. Withdrawing works.
  • No personal or sensitive data in localStorage (email, address, tokens, card details).
  • Clearing cookies mid-session, or blocking cookies entirely in browser settings, produces a helpful message, not a broken site.

Common bugs

#BugWhat you seeTypical severity
1Logout doesn’t clear the tokenToken stays in localStorage; Reload or Back logs you back inCritical
2Session never expiresStill logged in after hours of inactivity; server accepts old tokensHigh
3Session cookie missing HttpOnly / Securedocument.cookie shows the session ID; no ✓ in the HttpOnly/Secure columnsHigh
4“Remember me” ignoredCookie has an expiry date even when unchecked, or none when checkedMedium–High
5Reject doesn’t rejectAnalytics cookies and requests appear after “Reject all”High (legal)
6Cookies set before consent_ga or ad cookies exist before you click the bannerHigh (legal)
7Data leaks between usersPrevious user’s cart, name or address shown after logout/login on the same browserHigh–Critical
8Sensitive data in web storageEmail, address, tokens or card data in localStorageHigh
9Crash when a cookie is missingDeleting a cookie gives a blank page or endless spinner instead of “Please log in”Medium
10Cart lost on loginGuest cart disappears when the user logs inMedium

Find the bug

Here’s another build of Pantry, with six bugs. Watch the Application panel closely after every action, and use the browser controls.

  • Make a cookie choice, then look at the Cookies table.
  • Log in (with and without “Remember me”), then log out and reload.
  • Check the flags on session_id.
  • Quit the browser, wait, and log in as a different user.

🐞 Bug hunt: Pantry shop storage

This demo has 6 hidden bugs. Explore it like a tester, then check your findings.

Found0/6
pantry.example
Free delivery on orders over €40
Pantry
Guest 0

Log in

Test accounts, password pre-filled.

  • Olive oil, 750 ml€8.90
  • Coffee beans, 1 kg€11.50
  • Fusilli pasta, 500 g€1.80

Your cart

Empty

DevTools›Application
https://pantry.example

No cookies for this site.

Select a row to see its full value.

Browser controls

Tue 13 Oct, 09:00

  • → Page loaded. No cookies yet: the consent banner is waiting for your choice.
  1. 1

    Hint: Click Reject all and look at the Cookies table.

  2. 2

    Hint: Log in, log out, check Local storage, then press Reload.

  3. 3

    Hint: Log in and select session_id in the Cookies table.

  4. 4

    Hint: Log in with Remember me unchecked, look at the Expires column, then Quit & reopen browser.

  5. 5

    Hint: Log in as Anna, add items, log out, then log in as Ben.

  6. 6

    Hint: Log in without Remember me, delete auth_token, then use Wait 31 min.

More security checks like these are in Security Basics for Testers, and the full login flow is covered in Login and Sign Up.

Example test cases

TC-ST-001Logout removes the session and all auth data

Preconditions

  • User anna@test.com exists
  • DevTools open on Application

Steps

  1. Log in as anna@test.com
  2. Click Log out
  3. Check Cookies, Local storage and Session storage
  4. Reload the page
  5. Press Back

Expected result

No session cookie, token or personal data remains. After reload and Back the page shows the guest view.

TC-ST-002Session cookie has secure flags

Steps

  1. Log in
  2. Open Application › Cookies and select session_id
  3. In the Console, run document.cookie

Expected result

session_id has HttpOnly and Secure ticked and SameSite=Lax or Strict. It does not appear in the document.cookie output.

TC-ST-003Without "Remember me", quitting the browser ends the session

Steps

  1. Log in with Remember me unchecked
  2. Check that session_id expires at "Session"
  3. Quit the browser completely and reopen the site

Expected result

The user is logged out and sees the login form.

TC-ST-004Idle session expires after 30 minutes

Preconditions

  • Idle timeout configured to 30 minutes (ask devs for a shorter timeout on the test environment)

Steps

  1. Log in without Remember me
  2. Do nothing for 31 minutes
  3. Add a product to the cart

Expected result

The request returns 401. The page shows "Your session expired. Please log in again." The product is not lost.

TC-ST-005Rejecting cookies sets no analytics cookies or requests

Preconditions

  • Fresh Incognito window
  • DevTools open on Application and Network

Steps

  1. Open the site and check cookies before clicking anything
  2. Click Reject all
  3. Browse two more pages

Expected result

Before and after rejecting, only necessary cookies exist (plus cookie_consent). No requests go to analytics or ad domains.

TC-ST-006Next user doesn't see the previous user's cart

Steps

  1. Log in as anna@test.com and add 2 items
  2. Log out
  3. Log in as ben@test.com

Expected result

Ben sees only his own cart. Anna's items are not shown and not in localStorage.

TC-ST-007Deleting the session cookie mid-session is handled gracefully

Steps

  1. Log in
  2. Delete session_id in Application › Cookies
  3. Add a product to the cart

Expected result

The app shows a "Please log in again" message. No crash, blank page or endless spinner.

Tip: click a test case to expand it.

Checklist

Cookies, sessions and storage checklist

0 of 15 checked

Check your understanding

Quick quiz

0/5 answered · 0 correct

  1. 1.In DevTools, a cookie shows "Session" in the Expires / Max-Age column. What does that mean?

  2. 2.Which flag stops page JavaScript, including injected scripts, from reading a cookie?

  3. 3.A user dismisses a banner, the site saves that in sessionStorage. When will the banner come back?

  4. 4.After clicking "Reject all" on the consent banner, you see a _ga cookie in the Application panel. What is this?

  5. 5.You log out, then reload, and you are logged in again. Where should you look first?

Key takeaways

  • Cookies travel to the server with every request. localStorage and sessionStorage stay in the browser. sessionStorage dies with the tab.
  • Session cookies have no expiry and vanish when the browser closes. Persistent cookies live until their date.
  • Auth cookies need HttpOnly, Secure and SameSite. Tokens and personal data don’t belong in localStorage.
  • Logout clears nothing by itself. The app must end the server session and delete every token and personal item in the browser.
  • Test expiry, “Remember me”, multiple tabs, private windows, deleting cookies mid-session and switching users on one browser.
  • Consent banners: nothing optional before a choice, Reject as easy as Accept, and Reject must really reject. Verify it in the Application and Network panels.

Finished this page?Nice work, this page is complete!

Mark it as done to track your progress. It's saved in this browser, no account needed.

Its review cards are now in Bites ⚡
Esc

Type to search the whole site.