reading, writing and watching structured cookies live
The Cookie Store API replaces the error prone parsing of document.cookie with an asynchronous, promise based interface featuring structured cookie objects, change events and real service worker access. Anyone managing session cookies, consent banners or auth tokens will find a much more robust foundation in the Cookie Store API than manual string parsing.
Table of Contents
- 1. Why document.cookie is a dead end
- 2. Basics: get, getAll, set and delete
- 3. Structured attributes instead of string concatenation
- 4. The change event: watching cookies live
- 5. Cookie access inside a service worker
- 6. SameSite, partitioned and security attributes
- 7. Practical example: consent management with the Cookie Store API
- 8. Fallback strategy and browser support
- 9. Cookie Store API compared to document.cookie
- 10. Summary
- 11. FAQ
1. Why document.cookie is a dead end
Since the earliest days of the web, document.cookie has been the only native interface for accessing cookies from JavaScript, and it was misdesigned from the start: a single string getter and setter that returns every cookie of a document as one contiguous, semicolon separated format, with no structure whatsoever. Every application that wanted to read a single cookie had to parse that string itself, URL decode it, and search for a name, a pattern reimplemented slightly differently and error prone in countless projects. The Cookie Store API is the overdue answer to that problem.
With the Cookie Store API, accessible through the global object cookieStore, every cookie becomes a structured JavaScript object with named properties such as name, value, domain, path, expires and sameSite. Instead of a raw string, the Cookie Store API returns an array of objects or a single object, with no manual parsing at all. This not only reduces code, it eliminates an entire class of bugs caused by faulty URL decoding or incorrect split behavior with special characters in cookie values.
The second fundamental difference between the Cookie Store API and document.cookie is asynchronicity: every method returns a promise, which allows access even from contexts without synchronous DOM access, above all service workers. That was simply impossible with document.cookie, since that property only exists in the document context. The Cookie Store API thereby closes a gap that has affected offline first applications and push notification handlers for years.
2. Basics: get, getAll, set and delete
The four central methods of the Cookie Store API are cookieStore.get(), cookieStore.getAll(), cookieStore.set() and cookieStore.delete(). All four accept either a simple string name or an options object with additional filter criteria such as url for path specific queries. The return value of get() is either a single cookie object or null, while getAll() always returns an array, even if no cookie matches.
A decisive advantage of the Cookie Store API over document.cookie is that set() actually reports whether the write succeeded, through the resolved promise. With document.cookie = "..." there is no feedback about whether the cookie was actually set, for instance because an invalid attribute silently discarded the whole assignment. With the Cookie Store API, a failed write can reliably be detected through a rejected promise or a subsequent verification with get().
// Cookie Store API: reading and writing without manual string parsing
async function readSessionCookie() {
const cookie = await cookieStore.get("session_id");
return cookie ? cookie.value : null;
}
async function writeSessionCookie(value) {
await cookieStore.set({
name: "session_id",
value,
path: "/",
expires: Date.now() + 1000 * 60 * 60 * 24, // 24 hours from now, in ms
sameSite: "lax",
});
}
async function listAllCookies() {
const cookies = await cookieStore.getAll();
return cookies.map((c) => ({ name: c.name, value: c.value }));
}
async function removeSessionCookie() {
await cookieStore.delete("session_id");
}
3. Structured attributes instead of string concatenation
With document.cookie, attributes such as expires, path, domain and SameSite all have to be strung together as part of a single string literal, for example "name=value; expires=Wed, 09 May 2026 12:00:00 GMT; path=/; SameSite=Lax". This construction is error prone because every date format has to be manually formatted correctly, and typos in attribute names are silently ignored instead of throwing an error. The Cookie Store API replaces this with a typed object where expires is a timestamp in milliseconds, not a formatted string.
For cookies with a future expiration date, the Cookie Store API computes the correct format internally, so developers never have to deal with RFC 1123 date formats or timezone quirks. Another structural advantage: the partitioned attribute for partitioned cookies in the context of third party embeds can be set as a simple boolean, instead of being woven into the cookie definition as yet another string fragment.
// Structured cookie attributes instead of manual string building
async function setPartitionedAnalyticsCookie() {
await cookieStore.set({
name: "analytics_id",
value: crypto.randomUUID(),
path: "/",
sameSite: "none",
secure: true,
partitioned: true, // scoped to the embedding top-level site
expires: Date.now() + 1000 * 60 * 60 * 24 * 30, // 30 days
});
}
4. The change event: watching cookies live
One capability that simply does not exist with document.cookie is a native event for cookie changes. Developers previously had to use polling intervals that repeatedly read document.cookie and compare it to the previous state to detect changes, an inefficient and delayed pattern. The Cookie Store API instead delivers a real change event through cookieStore.addEventListener("change", handler), fired immediately whenever a cookie is set, changed, or deleted.
The event object of the Cookie Store API contains two arrays, changed and deleted, each with the affected cookie objects. This lets an application react specifically to certain cookie names, for example updating the user interface as soon as a consent cookie changes that was set in another tab or by a server response. This kind of reactivity was only simulable before the Cookie Store API through elaborate workarounds using StorageEvent at the local storage level, and even that did not work for actual cookies.
// React to cookie changes in real time with the Cookie Store API
cookieStore.addEventListener("change", (event) => {
for (const cookie of event.changed) {
if (cookie.name === "consent_status") {
console.log("Consent changed to:", cookie.value);
updateConsentUI(cookie.value);
}
}
for (const cookie of event.deleted) {
if (cookie.name === "session_id") {
console.warn("Session cookie was deleted, redirecting to login");
redirectToLogin();
}
}
});
5. Cookie access inside a service worker
Arguably the biggest practical breakthrough of the Cookie Store API is access to cookies directly inside a service worker, through self.cookieStore. Before this API, a service worker that wanted to decide, for instance, whether an authenticated request was present had to take a detour through postMessage() with the main thread, because document.cookie does not exist at all in the worker context. The Cookie Store API makes that detour unnecessary and allows direct, asynchronous cookie access exactly where fetch events are intercepted.
This becomes especially valuable in combination with the cookiechange event in the service worker context, which lets a service worker react to cookie changes even when no document tab is actively open, for example during push notification processing. For offline first applications with their own auth handling inside the service worker, the Cookie Store API is therefore a central building block for steering cache strategies based on the current session status.
// service-worker.js — reading cookies directly inside the worker
self.addEventListener("fetch", (event) => {
event.respondWith(
(async () => {
const authCookie = await cookieStore.get("auth_token");
if (!authCookie && isProtectedRequest(event.request)) {
return new Response("Unauthorized", { status: 401 });
}
return fetch(event.request);
})()
);
});
// Also available: reacting to cookie changes inside the worker
self.cookieStore.addEventListener("change", (event) => {
if (event.deleted.some((c) => c.name === "auth_token")) {
self.registration.showNotification("Session expired");
}
});
6. SameSite, partitioned and security attributes
The Cookie Store API represents all relevant security attributes of modern cookies in a structured way: sameSite accepts the values "strict", "lax" or "none", secure is a boolean for HTTPS only cookies, and partitioned enables the CHIPS specification, Cookies Having Independent Partitioned State, for third party cookies that are stored isolated per embedding top level site. This explicit, typed representation prevents an attribute from being accidentally omitted because a typo in the string format goes unnoticed.
An important security aspect of the Cookie Store API: HttpOnly cookies remain invisible to JavaScript, even through cookieStore. This is intentional and ensures the Cookie Store API does not bypass existing protections against XSS attacks. Applications that set sensitive session tokens server side as HttpOnly do not directly benefit from the Cookie Store API for those tokens, but can cleanly manage all client side relevant cookies, such as UI preferences or consent status, through it.
7. Practical example: consent management with the Cookie Store API
A realistic use case for the Cookie Store API is a consent management system for cookie banners that needs to stay consistent across multiple tabs. As soon as a user consents to cookie usage in one tab, that decision should immediately be visible in every other open tab, without requiring a reload. With the change event of the Cookie Store API this can be implemented without additional communication channels like a broadcast channel, since setting a cookie in one tab automatically triggers an event in every other tab of the same origin.
This property of the Cookie Store API makes consent banner implementations considerably more robust, because synchronization no longer has to be manually rebuilt through local storage events, which only apply to local storage in the first place, not to cookies. For GDPR compliant consent management, where consent has to be logged server side and respected client side, the Cookie Store API delivers a much cleaner foundation than the previous interplay of document.cookie and a self built event bus.
// Consent banner synced across tabs via the Cookie Store API change event
async function acceptConsent() {
await cookieStore.set({
name: "consent_status",
value: "accepted",
path: "/",
expires: Date.now() + 1000 * 60 * 60 * 24 * 365,
sameSite: "lax",
});
hideConsentBanner();
}
cookieStore.addEventListener("change", (event) => {
const consentChange = event.changed.find((c) => c.name === "consent_status");
if (consentChange?.value === "accepted") {
hideConsentBanner(); // reflects instantly in every open tab
}
});
8. Fallback strategy and browser support
The Cookie Store API has been available in Chrome and Edge since version 87 and in all Chromium based browsers, while Firefox and Safari had not fully implemented the specification at the time this article was written. For production applications, feature detection with "cookieStore" in globalThis is recommended, combined with a fallback to classic document.cookie parsing for unsupported browsers.
A robust fallback strategy wraps both implementations behind a unified interface, so the rest of the application only programs against that abstraction rather than directly against the Cookie Store API or document.cookie. This also simplifies the eventual full migration once every target browser supports the Cookie Store API, because only the abstraction layer's implementation needs to be swapped, not the entire application code.
9. Cookie Store API compared to document.cookie
The following table compares typical cookie operations using classic document.cookie against the structured Cookie Store API.
| Task | document.cookie | Cookie Store API | Benefit |
|---|---|---|---|
| Reading a single cookie | Manual splitting and decoding of the string | cookieStore.get(name) |
Structured object, no parsing |
| Setting an expiration date | RFC 1123 date format as a string | expires: Date.now() + ms |
Timestamp in milliseconds, no formatting |
| Access inside a service worker | Not possible, no document context | self.cookieStore |
Direct, asynchronous access in the worker |
| Reacting to changes | Polling interval with string comparison | cookieStore.addEventListener("change") |
Immediate, native event |
| Checking write success | No feedback, manual verification | Promise from set() |
Failures become detectable |
The Cookie Store API solves nearly every structural weakness of document.cookie: missing parsing format, no feedback on success, no access outside the document context, and no native change event. For new projects that actively manage cookies, the Cookie Store API with an appropriate fallback is the clearly more robust choice.
Mironsoft
JavaScript architecture, cookie management and consent systems
Cookie handling without error prone string parsing?
We migrate existing document.cookie handling to the Cookie Store API, implement service worker auth checks, and build consent systems with live synchronization across tabs.
Migration
Replacing document.cookie parsing with the structured Cookie Store API
Service worker integration
Cookie based auth checks directly inside the service worker's fetch handler
Consent systems
GDPR compliant consent banners with live synchronization via change events
10. Summary
The Cookie Store API replaces decades old, error prone string parsing of document.cookie with an asynchronous, structured, promise based interface. With get(), getAll(), set() and delete(), cookies can be managed without manual encoding, while the native change event enables live reactions to cookie changes, with no polling at all. Access through self.cookieStore inside a service worker closes a gap that previously could only be solved through detours via postMessage().
For consent management, session handling, and every use case where cookies need to stay in sync across tabs, the Cookie Store API delivers a considerably more robust technical foundation than the previous interplay of document.cookie and self built synchronization mechanisms. With a clean feature detection and fallback strategy, the Cookie Store API can already be used in production today, while the remaining browsers catch up.
Cookie Store API — the essentials at a glance
Core methods
get(), getAll(), set(), delete() return and accept structured cookie objects, all as promises.
change event
Native event for cookie changes, fully replaces polling intervals.
Service worker
self.cookieStore allows cookie access where document.cookie was never available.
Browser support
Chrome/Edge fully, Firefox/Safari not yet, feature detection with a fallback is required.