Beyond cookies: LocalStorage, SessionStorage and IndexedDB
Basics
You click “Reject”, the cookie list stays short – and on your next visit the website recognises you anyway. No cookie involved, no entry in the overview, and in many audit reports the identifier simply does not appear. It lives in LocalStorage.
That is not a gap in the law, it is a gap in the testing routine: cookies are only one of several drawers a website can put something into. The rule behind it takes no interest in the drawer.
What the rule says – and what it does not
Article 5(3) of the ePrivacy Directive, and Germany's § 25 TDDDG implementing it, tie consent to two operations: storing information on the user's terminal equipment, and gaining access to information already stored there. The word cookie does not appear in the German provision at all. The exceptions cover the transmission of a message and whatever is strictly necessary for a service the user explicitly requested.
The European Data Protection Board spelled out this technology-neutral reading in its Guidelines 2/2023 on the technical scope of Article 5(3), final version adopted in October 2024: browser storage sits there alongside tracking pixels, URL parameters, unique identifiers and information processed locally in the browser. The German supervisory authorities' guidance for providers of digital services likewise names LocalStorage and SessionStorage explicitly next to cookies.
Three stores, three lifetimes
Technically these are separate mechanisms with different behaviour:
- LocalStorage: text key-value pairs, roughly 5 MB per origin, no expiry date – it stays until someone deletes it
- SessionStorage: same design, but per tab; close the tab and the content is gone
- IndexedDB: a small database inside the browser for structured data, sized by disk space – hundreds of megabytes and up
- Cookies for comparison: around 4 KB per entry, with an expiry date, and they travel along automatically with every matching request
The difference that makes audits fail
That last bullet is the decisive one. A cookie attaches itself to every request to the matching domain – in the network tab you can read it in the request header. LocalStorage, SessionStorage and IndexedDB never leave the browser on their own. For a value to travel anywhere, a script has to read it and write it into a request.
For testing this means: looking only at network traffic shows you the consequence at best, never the entry itself. And if the script sends the identifier later – on the next page view, on the next click, or only after consent – then there is nothing to see in the network tab at all, even though the write happened long before.
What typically sits there
Browser storage is an ordinary tool first of all: an unfinished shopping cart, the chosen language, a form that survives a reload. It becomes relevant to recognition with other entries – a visitor or device ID, the assigned variant of an A/B test, the buffer of a session recording, collected events waiting to be sent in a batch. And in almost every setup the consent decision itself lives there too.
Purpose decides, not the drawer. The stored consent is precisely the entry without which your choice would be lost on the next click. An ID that lets analytics or advertising recognise you is a different matter – even though both sit in the same LocalStorage. Where the line runs in your case is a question for your privacy counsel; what actually gets written is something you can check yourself.
Browsers clean up, but they do not manage consent
Browser vendors have responded to recognition via web storage. Since 2020 Safari deletes all script-writable storage when a website goes seven days without interaction – LocalStorage, SessionStorage, IndexedDB and service worker registrations included. Since version 103 Firefox partitions storage by the top-level site by default, so an embedded service on two websites sees two separate stores instead of one shared one; Chrome does the same for embedded third-party contexts since 2023.
That limits the reach of recognition, but it answers a different question than the legal one: whether the entry was allowed to be written before consent in the first place. And it is useless as an audit result, because every browser cleans up differently – what disappears in Safari after a week is still sitting there in Chrome.
Why many banner setups miss this
Two patterns keep showing up. The first: the consent tool blocks external scripts by category and dutifully waits for consent – while the site's own code does not, and drops its ID immediately. The second: clicking “Reject” deletes cookies, and the storage entries stay put. On the next visit the script reads the same identifier again – and that is the second operation the rule covers, gaining access to information already stored.
Neither shows up in a cookie list. It is named after what it shows.
How to check for yourself
Open your website in a private window, then the developer tools. In the application-data section, LocalStorage, SessionStorage and IndexedDB sit right next to the cookies. Check them in the same three phases you use for cookies:
First, before any interaction with the banner – note which entries are already there. Second, after clicking “Reject”, ideally with a reload: what disappeared, what did not, what is new? Third, after accepting, as a yardstick for what the setup writes at all. The interesting values are the ones that look like an identifier – long random strings, timestamps, recurring numbers – and that stay the same between two private windows.
The rule does not distinguish by technology but by operation: storing on the device and accessing what is stored. That covers LocalStorage exactly as it covers a cookie. Whether a specific entry falls under the exception for strictly necessary functions depends on its purpose – settle that with your privacy counsel, not by the name of the drawer.
No. Cookies attach themselves to matching requests, web storage does not. A value only surfaces in network traffic once a script reads it and sends it along – and that can happen much later than the write. To see it, look at the storage section of your developer tools.
Not if the same identifier also sits in LocalStorage or IndexedDB: it stays there and gets read again on the next visit. So after rejecting, check every store, not just the cookie list.
Partly. Safari clears script-writable storage after seven days without interaction with the site, and Firefox and Chrome partition the storage of embedded services by the site on top. That limits recognition, but it does not replace consent – and because every browser cleans up differently, it is not a reliable yardstick for an audit.
Measure first, discuss after
The Cookienator visits your website like a real visitor – before consent, after rejecting, after accepting – and shows you for each phase which cookies get set and which requests actually go out. The look into LocalStorage and IndexedDB then takes you two minutes yourself.
Scan your website now