Cookie Store API in Detail: Asynchronous Cookie Management Beyond document.cookie
AI generated
JS
() =>
JavaScript · Cookies · Service Worker · Web Storage
Cookie Store API in detail: asynchronous cookie management beyond document.cookie
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.

18 min read cookieStore · change event · Service Worker · SameSite Chrome · Edge · Firefox (in progress)

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.

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.

11. FAQ: Cookie Store API

1What is the Cookie Store API?
Asynchronous, promise based interface for cookie access via cookieStore, replaces document.cookie parsing.
2How do I read a single cookie?
With cookieStore.get(name), returns a structured object or null.
3Access to HttpOnly cookies?
No, stay invisible to JavaScript, even through the Cookie Store API, deliberate XSS protection.
4Detect changes without polling?
With addEventListener change, event contains changed and deleted arrays.
5Works inside a service worker?
Yes, via self.cookieStore, never possible with document.cookie.
6How do I set an expiration date?
Via expires as a millisecond timestamp, no date format needed.
7What is the partitioned attribute?
Enables CHIPS, isolates third party cookies per embedding top level site.
8Check write success?
Promise from set() only resolves on success, document.cookie offers no such feedback.
9Which browsers support it?
Chrome/Edge from 87 and Chromium browsers, Firefox/Safari not yet fully.
10How do I build a fallback?
Feature detection with 'cookieStore' in globalThis, encapsulated abstraction layer for both implementations.