Parsing and Deleting Browser Cookies With JS

A complete tutorial on parsing and deleting browser cookies with JavaScript. Covers cookie string parsing, regex-based extraction, URL-decoded cookie values, deleting cookies with matching attributes, bulk deletion, cookie expiration detection, building a cookie parser class, and advanced cookie management utilities.

JavaScriptintermediate
14 min read

document.cookie returns a flat string of key-value pairs. Parsing this string correctly, handling encoded values, and deleting cookies with matching attributes requires careful utility code. This guide covers robust parsing, targeted deletion, and building a production-ready cookie toolkit.

For setting cookies and understanding attributes, see how to manage cookies in JS complete tutorial.

javascriptjavascript
// document.cookie returns a semicolon-separated string
console.log(document.cookie);
// "username=parth; theme=dark; lang=en; prefs=%7B%22font%22%3A16%7D"
 
// Important: only name=value pairs are visible
// Attributes (path, domain, expires, etc.) are NOT included in the string
// HttpOnly cookies are NOT included

Parsing All Cookies

Simple Parser

javascriptjavascript
function parseCookies(cookieString = document.cookie) {
  if (!cookieString) return {};
 
  return cookieString.split("; ").reduce((cookies, pair) => {
    const separatorIndex = pair.indexOf("=");
 
    if (separatorIndex === -1) {
      cookies[pair.trim()] = "";
      return cookies;
    }
 
    const key = decodeURIComponent(pair.slice(0, separatorIndex).trim());
    const value = decodeURIComponent(pair.slice(separatorIndex + 1).trim());
    cookies[key] = value;
 
    return cookies;
  }, {});
}
 
const cookies = parseCookies();
console.log(cookies);
// { username: "parth", theme: "dark", lang: "en", prefs: '{"font":16}' }

Robust Parser With Edge Cases

javascriptjavascript
function parseRobust(cookieString = document.cookie) {
  const cookies = new Map();
 
  if (!cookieString || cookieString.trim() === "") {
    return cookies;
  }
 
  // Split on "; " but handle malformed strings
  const pairs = cookieString.split(/;\s*/);
 
  for (const pair of pairs) {
    if (!pair) continue;
 
    const eqIndex = pair.indexOf("=");
 
    if (eqIndex === -1) {
      // Cookie with no value
      cookies.set(pair.trim(), "");
      continue;
    }
 
    const name = pair.slice(0, eqIndex).trim();
    let value = pair.slice(eqIndex + 1).trim();
 
    // Remove surrounding quotes if present
    if (value.startsWith('"') && value.endsWith('"')) {
      value = value.slice(1, -1);
    }
 
    try {
      cookies.set(decodeURIComponent(name), decodeURIComponent(value));
    } catch {
      // Malformed URI encoding, store raw
      cookies.set(name, value);
    }
  }
 
  return cookies;
}
 
const cookieMap = parseRobust();
console.log(cookieMap.get("theme")); // "dark"
console.log(cookieMap.has("username")); // true

By Name Lookup

javascriptjavascript
function getCookie(name) {
  const encoded = encodeURIComponent(name);
  const pairs = document.cookie.split("; ");
 
  for (const pair of pairs) {
    const eqIndex = pair.indexOf("=");
    const key = eqIndex === -1 ? pair : pair.slice(0, eqIndex);
 
    if (key === encoded || decodeURIComponent(key) === name) {
      return eqIndex === -1
        ? ""
        : decodeURIComponent(pair.slice(eqIndex + 1));
    }
  }
 
  return null;
}
 
console.log(getCookie("theme")); // "dark"
console.log(getCookie("missing")); // null

Regex-Based Extraction

javascriptjavascript
function getCookieRegex(name) {
  const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  const match = document.cookie.match(
    new RegExp(`(?:^|;\\s*)${escaped}=([^;]*)`)
  );
 
  if (!match) return null;
  return decodeURIComponent(match[1]);
}
 
console.log(getCookieRegex("username")); // "parth"
javascriptjavascript
function getCookieAsNumber(name, fallback = 0) {
  const value = getCookie(name);
  if (value === null) return fallback;
  const num = Number(value);
  return Number.isNaN(num) ? fallback : num;
}
 
function getCookieAsBoolean(name, fallback = false) {
  const value = getCookie(name);
  if (value === null) return fallback;
  return value === "true" || value === "1";
}
 
function getCookieAsJSON(name, fallback = null) {
  const value = getCookie(name);
  if (value === null) return fallback;
  try {
    return JSON.parse(value);
  } catch {
    return fallback;
  }
}
 
// Usage
const fontSize = getCookieAsNumber("fontSize", 16);
const darkMode = getCookieAsBoolean("darkMode", false);
const prefs = getCookieAsJSON("prefs", { sidebar: true });

Deleting Cookies

Basic Deletion

javascriptjavascript
function deleteCookie(name, path = "/") {
  document.cookie = `${encodeURIComponent(name)}=; max-age=0; path=${path}`;
}
 
deleteCookie("theme");

Deletion With All Matching Attributes

javascriptjavascript
function deleteCookieFull(name, options = {}) {
  const parts = [`${encodeURIComponent(name)}=`, "max-age=0"];
 
  // Must match the original path
  parts.push(`path=${options.path || "/"}`);
 
  // Must match the original domain
  if (options.domain) {
    parts.push(`domain=${options.domain}`);
  }
 
  if (options.secure) {
    parts.push("secure");
  }
 
  if (options.sameSite) {
    parts.push(`samesite=${options.sameSite}`);
  }
 
  document.cookie = parts.join("; ");
}
 
// Delete a cookie that was set on a specific domain
deleteCookieFull("tracking", {
  path: "/",
  domain: ".example.com",
  secure: true,
  sameSite: "none",
});

Why Deletion Fails

ReasonExplanationFix
Wrong pathCookie was set with path=/app but you deleted with path=/Match the original path
Wrong domainCookie was set with domain=.example.comSpecify the same domain
HttpOnly cookieCannot be accessed or deleted via JSMust delete server-side
Secure on HTTPSecure cookies require HTTPSUse HTTPS or remove Secure flag
javascriptjavascript
function deleteAllCookies(path = "/") {
  const cookies = parseCookies();
 
  for (const name of Object.keys(cookies)) {
    deleteCookie(name, path);
  }
 
  return Object.keys(cookies).length;
}
 
function deleteByPrefix(prefix, path = "/") {
  const cookies = parseCookies();
  let count = 0;
 
  for (const name of Object.keys(cookies)) {
    if (name.startsWith(prefix)) {
      deleteCookie(name, path);
      count++;
    }
  }
 
  return count;
}
 
function deleteByPattern(pattern, path = "/") {
  const cookies = parseCookies();
  const regex = pattern instanceof RegExp ? pattern : new RegExp(pattern);
  let count = 0;
 
  for (const name of Object.keys(cookies)) {
    if (regex.test(name)) {
      deleteCookie(name, path);
      count++;
    }
  }
 
  return count;
}
 
// Delete all cookies
const deleted = deleteAllCookies();
console.log(`Deleted ${deleted} cookies`);
 
// Delete all analytics cookies
deleteByPrefix("_ga");
 
// Delete cookies matching a pattern
deleteByPattern(/^(utm_|_ga|_gid)/);
javascriptjavascript
class CookieParser {
  constructor() {
    this.cache = null;
    this.cacheSource = null;
  }
 
  parse(cookieString = document.cookie) {
    // Cache parsed result if source string hasn't changed
    if (cookieString === this.cacheSource && this.cache) {
      return this.cache;
    }
 
    const result = {};
 
    if (!cookieString) {
      this.cache = result;
      this.cacheSource = cookieString;
      return result;
    }
 
    const pairs = cookieString.split(/;\s*/);
 
    for (const pair of pairs) {
      const eqIndex = pair.indexOf("=");
      if (eqIndex === -1) continue;
 
      const name = pair.slice(0, eqIndex).trim();
      let value = pair.slice(eqIndex + 1).trim();
 
      if (value.startsWith('"') && value.endsWith('"')) {
        value = value.slice(1, -1);
      }
 
      try {
        result[decodeURIComponent(name)] = decodeURIComponent(value);
      } catch {
        result[name] = value;
      }
    }
 
    this.cache = result;
    this.cacheSource = cookieString;
    return result;
  }
 
  get(name) {
    return this.parse()[name] ?? null;
  }
 
  has(name) {
    return name in this.parse();
  }
 
  names() {
    return Object.keys(this.parse());
  }
 
  values() {
    return Object.values(this.parse());
  }
 
  entries() {
    return Object.entries(this.parse());
  }
 
  count() {
    return Object.keys(this.parse()).length;
  }
 
  invalidateCache() {
    this.cache = null;
    this.cacheSource = null;
  }
 
  toJSON() {
    return this.parse();
  }
 
  toString() {
    return document.cookie;
  }
}
 
// Usage
const parser = new CookieParser();
 
console.log(parser.get("theme")); // "dark"
console.log(parser.has("username")); // true
console.log(parser.names()); // ["username", "theme", "lang"]
console.log(parser.count()); // 3
 
// After setting a new cookie, invalidate cache
document.cookie = "newCookie=value; path=/";
parser.invalidateCache();
console.log(parser.count()); // 4
javascriptjavascript
class CookieConsent {
  constructor(consentCookieName = "cookie_consent") {
    this.consentKey = consentCookieName;
    this.categories = ["necessary", "analytics", "marketing", "preferences"];
  }
 
  getConsent() {
    const raw = getCookie(this.consentKey);
    if (!raw) return null;
    try {
      return JSON.parse(raw);
    } catch {
      return null;
    }
  }
 
  setConsent(categories) {
    const consent = {
      categories,
      timestamp: new Date().toISOString(),
      version: "1.0",
    };
 
    document.cookie = [
      `${this.consentKey}=${encodeURIComponent(JSON.stringify(consent))}`,
      `max-age=${365 * 86400}`,
      "path=/",
      "samesite=lax",
      "secure",
    ].join("; ");
 
    // Remove cookies for denied categories
    this.enforceDenials(categories);
  }
 
  hasConsent(category) {
    const consent = this.getConsent();
    if (!consent) return category === "necessary";
    return consent.categories.includes(category);
  }
 
  enforceDenials(allowed) {
    const denied = this.categories.filter((c) => !allowed.includes(c));
 
    const cookieCategoryMap = {
      analytics: /^(_ga|_gid|_gat|__utm)/,
      marketing: /^(_fbp|_fbc|fr|__adroll)/,
      preferences: /^(lang|theme|sidebar)/,
    };
 
    for (const category of denied) {
      const pattern = cookieCategoryMap[category];
      if (pattern) {
        deleteByPattern(pattern);
      }
    }
  }
 
  revokeAll() {
    this.setConsent(["necessary"]);
  }
}
 
const consent = new CookieConsent();
consent.setConsent(["necessary", "preferences"]);
console.log(consent.hasConsent("analytics")); // false
Rune AI

Rune AI

Key Insights

  • Split on "; " then on first "=": Cookie values can contain = characters; always split on the first occurrence only
  • Always decode with decodeURIComponent: Cookie names and values may be percent-encoded; wrap decoding in try/catch for malformed strings
  • Match path and domain when deleting: The browser identifies cookies by name + path + domain; mismatched attributes create new entries instead of removing existing ones
  • HttpOnly cookies are invisible to JS: They do not appear in document.cookie and cannot be deleted client-side; manage them server-side only
  • Cache parsed results: Parsing document.cookie on every access is wasteful; cache the result and invalidate when cookies change
RunePowered by Rune AI

Frequently Asked Questions

Why does document.cookie not show all my cookies?

`document.cookie` only shows cookies accessible to JavaScript on the current path and origin. HttpOnly cookies, cookies set on a different path, and cookies from a different domain are not visible. Use browser DevTools (Application tab) to see all cookies.

How do I parse cookies from a Set-Cookie header in Node.js?

On the server, parse the `cookie` request header using the same splitting logic. The `Set-Cookie` response header has a different format that includes attributes. Libraries like `cookie` on npm handle both formats.

Can I detect when a cookie has expired?

Not directly from JavaScript. Expired cookies are automatically removed by the browser and simply stop appearing in `document.cookie`. Store the expiration timestamp alongside the cookie value (or in a companion cookie) to detect pending expiration.

Why does deleting a cookie sometimes not work?

The most common reason is a path or domain mismatch. A cookie set with `path=/admin` cannot be deleted with `path=/`. Similarly, a cookie set on `.example.com` must be deleted with the same domain. Also, HttpOnly cookies cannot be deleted via JavaScript.

How do I delete all cookies for the current site?

Use `deleteAllCookies("/")` to delete all visible cookies on the root path. However, cookies set on specific subpaths or different domains require matching attributes. There is no single API call to delete all cookies across all paths and domains.

Conclusion

Robust cookie parsing requires handling URL encoding, quoted values, missing values, and malformed strings. Cookie deletion demands matching the original path and domain attributes. Build utility classes like CookieParser and CookieConsent to encapsulate complexity. For setting cookies with proper attributes, see how to manage cookies in JS complete tutorial. For client-only storage alternatives, see JS localStorage API guide and JS sessionStorage API guide.