JavaScript reads and writes cookies through one property: document.cookie. Writing to it sets one cookie; reading it returns all cookies for the page as a single string. There is no built-in delete — you overwrite the cookie with an expiry in the past.
Quick answer:
// Set (expires in 7 days)
document.cookie = "theme=dark; max-age=604800; path=/; samesite=lax";
// Read all cookies for this page
console.log(document.cookie); // "theme=dark; lang=en"
// Delete (path must match the one used when setting it)
document.cookie = "theme=; max-age=0; path=/";The rest of this guide gives you reusable setCookie, getCookie and deleteCookie functions, explains every cookie attribute and its default, and covers the mistakes that make cookies silently fail.
Tested in: Chrome 152 on localhost, October 2026. Browser support notes come from MDN's compatibility data.
What Are Cookies?
A cookie is a small name–value pair the browser stores for a site and sends back to that site's server with every matching request. That last part is what makes cookies different from localStorage: the server sees them too.
- Sessions: keeping a user logged in between pages and visits.
- Preferences: language, theme, consent choices.
- Analytics and ads: recognising returning visitors.
Because cookies travel with every request, keep them small and only store what the server actually needs.
Cookie Attributes and Their Defaults
Everything after the first name=value pair is an attribute. Most cookie bugs come from not knowing what happens when an attribute is left out:
| Attribute | What it does | If you leave it out |
|---|---|---|
| max-age / expires | How long the cookie lives. max-age is in seconds; expires takes a UTC date string. | Session cookie: removed when the browsing session ends. |
| path | Which URL paths receive the cookie. | The current page's directory. Set from /blog/post.html it only applies under /blog — not to the whole site. |
| domain | Which hosts receive it. domain=example.com also covers subdomains. | Host-only: just the exact host that set it, no subdomains. |
| secure | Only sent over HTTPS. | Sent over HTTP and HTTPS. |
| samesite | Strict, Lax or None: whether it is sent on cross-site requests. | Chrome treats it as Lax. Firefox and Safari do not apply a Lax default, so set it explicitly. |
| httponly | Hides the cookie from JavaScript. | Readable by JavaScript. This flag can only be set by the server (Set-Cookie header); browsers ignore cookies that try to set it through document.cookie. |
Since Chrome 104, any expiry longer than 400 days is capped to 400 days. A cookie's name plus value can be at most 4096 bytes; anything larger is dropped without an error.
Setting a Cookie in JavaScript (js set cookie example)
The minimal version is a single assignment:
document.cookie = "username=JohnDoe; path=/";Assigning to document.cookie does not replace your other cookies — it adds or updates only the one you name. To avoid building the string by hand, use a helper:
function setCookie(name, value, options = {}) {
const { days, path = "/", domain, sameSite = "Lax", secure } = options;
let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
if (days !== undefined) cookie += `; max-age=${Math.round(days * 86400)}`;
cookie += `; path=${path}`;
if (domain) cookie += `; domain=${domain}`;
cookie += `; samesite=${sameSite}`;
if (secure || sameSite.toLowerCase() === "none") cookie += "; secure";
document.cookie = cookie;
}setCookie("theme", "dark", { days: 7 }); // persistent, 7 days
setCookie("cartId", "abc123"); // session cookie
setCookie("consent", "yes", { days: 180, secure: true });- encodeURIComponent is required: semicolons, commas and spaces would otherwise break the cookie string.
- max-age is simpler than expires because you do not have to build a date. Both work in all current browsers.
- The helper always sets path=/ so the cookie is visible on every page — usually what you want, and it makes deleting predictable.
- Chrome and Firefox reject samesite=None without secure, so the helper adds it automatically.
Reading Cookies in JavaScript (how to read a cookie)
Reading document.cookie gives you every cookie visible to the current page, separated by "; ". You only get names and values — never the expiry, path or other attributes.
function getCookie(name) {
for (const pair of document.cookie.split("; ")) {
const i = pair.indexOf("=");
if (i === -1) continue;
if (decodeURIComponent(pair.slice(0, i)) === name) {
return decodeURIComponent(pair.slice(i + 1));
}
}
return null;
}const theme = getCookie("theme"); // "dark", or null if it doesn't existTwo details matter here:
- Split on the first = only. A common snippet uses cookie.split("="), which turns the value eyJ0eXAi.sig== into eyJ0eXAi.sig. Base64 and JWT values regularly end in =.
- Compare whole names. Checking with includes or startsWith makes id match userid.
If you need everything at once:
function getAllCookies() {
const result = {};
if (!document.cookie) return result;
for (const pair of document.cookie.split("; ")) {
const i = pair.indexOf("=");
if (i === -1) continue;
result[decodeURIComponent(pair.slice(0, i))] = decodeURIComponent(pair.slice(i + 1));
}
return result;
}getAllCookies(); // { theme: "dark", lang: "en" }Deleting a Cookie in JavaScript (delete cookie js)
To delete a cookie, write it again with max-age=0 (or an expires date in the past). The browser only treats it as the same cookie if the name, path and domain all match the ones used when it was set.
function deleteCookie(name, options = {}) {
const { path = "/", domain } = options;
let cookie = `${encodeURIComponent(name)}=; max-age=0; path=${path}`;
if (domain) cookie += `; domain=${domain}`;
document.cookie = cookie;
}deleteCookie("theme"); // set with path=/
deleteCookie("draft", { path: "/editor" }); // set with path=/editor
deleteCookie("lang", { domain: "example.com" }); // set with domain=example.comIf a cookie "won't delete", it was almost always created with a different path or domain. A cookie set from /docs/page.html without a path lives under /docs, and deleteCookie(name) with path=/ leaves it untouched. Note that /docs/ and /docs are different paths.
A cookie set by the server with HttpOnly cannot be deleted from JavaScript at all — you need a server response that expires it.
Storing Objects in a Cookie
Cookies hold strings, so serialise objects with JSON:
setCookie("prefs", JSON.stringify({ lang: "en", fontSize: 16 }), { days: 30 });
const prefs = JSON.parse(getCookie("prefs") ?? "{}");
console.log(prefs.fontSize); // 16Keep it small. The JSON is sent to your server on every request, and the 4096-byte limit includes the URL-encoding.
The Modern Way: the cookieStore API
Newer browsers also offer an asynchronous Cookie Store API that works with objects instead of strings. It is available in Chrome 87+, Firefox 140+ and Safari 18.4+, and only on HTTPS pages (or localhost).
await cookieStore.set({
name: "theme",
value: "dark",
expires: Date.now() + 7 * 24 * 60 * 60 * 1000,
});
const cookie = await cookieStore.get("theme");
console.log(cookie?.value); // "dark"
await cookieStore.delete("theme");It reads and writes the same cookies as document.cookie. If you support older browsers, check for it first: if ("cookieStore" in window) { ... }.
Cookies vs localStorage vs sessionStorage
| Cookies | localStorage | sessionStorage | |
|---|---|---|---|
| Sent to the server | Yes, with every matching request | No | No |
| Size | 4096 bytes per cookie | About 5 MB per origin | About 5 MB per origin |
| Lifetime | Until expiry (max 400 days in Chrome) or end of session | Until cleared | Until the tab is closed |
| Can be hidden from JavaScript | Yes, with HttpOnly (server only) | No | No |
| Best for | Data the server needs: sessions, consent | Larger client-only data | Per-tab state |
If the server never needs the value, localStorage is usually the better choice.
Complete Example: Setting, Reading, and Deleting Cookies
A small page that sets, reads and deletes cookies and shows what document.cookie currently contains. Save it as an .html file and open it through a local server (npx serve or VS Code Live Server) — cookies do not work on file:// pages.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cookie Manager</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 480px; margin: 2rem auto; }
input, button { margin: 4px 0; padding: 6px; }
pre { background: #f4f4f4; padding: 12px; min-height: 2em; }
</style>
</head>
<body>
<input id="cookieName" placeholder="Cookie name">
<input id="cookieValue" placeholder="Cookie value">
<input id="cookieDays" type="number" placeholder="Days (empty = session)">
<div>
<button id="setBtn">Set</button>
<button id="readBtn">Read</button>
<button id="deleteBtn">Delete</button>
</div>
<p id="message"></p>
<pre id="allCookies"></pre>
<script>
// setCookie, getCookie and deleteCookie from the sections above
function setCookie(name, value, options = {}) {
const { days, path = "/", domain, sameSite = "Lax", secure } = options;
let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
if (days !== undefined) cookie += `; max-age=${Math.round(days * 86400)}`;
cookie += `; path=${path}`;
if (domain) cookie += `; domain=${domain}`;
cookie += `; samesite=${sameSite}`;
if (secure || sameSite.toLowerCase() === "none") cookie += "; secure";
document.cookie = cookie;
}
function getCookie(name) {
for (const pair of document.cookie.split("; ")) {
const i = pair.indexOf("=");
if (i === -1) continue;
if (decodeURIComponent(pair.slice(0, i)) === name) {
return decodeURIComponent(pair.slice(i + 1));
}
}
return null;
}
function deleteCookie(name, options = {}) {
const { path = "/", domain } = options;
let cookie = `${encodeURIComponent(name)}=; max-age=0; path=${path}`;
if (domain) cookie += `; domain=${domain}`;
document.cookie = cookie;
}
const nameInput = document.getElementById("cookieName");
const valueInput = document.getElementById("cookieValue");
const daysInput = document.getElementById("cookieDays");
const message = document.getElementById("message");
const allCookies = document.getElementById("allCookies");
function showAll() {
allCookies.textContent = document.cookie || "(no cookies)";
}
document.getElementById("setBtn").addEventListener("click", () => {
const name = nameInput.value.trim();
if (!name) return (message.textContent = "Enter a cookie name.");
const days = daysInput.value === "" ? undefined : Number(daysInput.value);
setCookie(name, valueInput.value, { days });
message.textContent = `Set "${name}".`;
showAll();
});
document.getElementById("readBtn").addEventListener("click", () => {
const value = getCookie(nameInput.value.trim());
message.textContent = value === null ? "Cookie not found." : `Value: ${value}`;
});
document.getElementById("deleteBtn").addEventListener("click", () => {
const name = nameInput.value.trim();
deleteCookie(name);
message.textContent = getCookie(name) === null
? `Deleted "${name}".`
: "Could not delete it (check path/domain).";
showAll();
});
showAll();
</script>
</body>
</html>Why Isn't My Cookie Working?
| Symptom | Likely cause |
|---|---|
| Cookie never appears | Page opened from file://, value over 4096 bytes, secure on a plain-HTTP page (other than localhost), samesite=None without secure (rejected by Chrome and Firefox), or httponly set from JavaScript. |
| Cookie won't delete | Path or domain differs from when it was set. Check the cookie's Path and Domain in DevTools → Application → Cookies. |
| Value is cut off | The reader splits on every "=", or the value was not encoded with encodeURIComponent. |
| Cookie disappears too soon | No max-age/expires (session cookie), or max-age given in days instead of seconds. |
| Cookie visible on one page but not another | It was set without path, so it is scoped to the directory of the page that set it. |
Security Best Practices for Cookies
- Keep session tokens out of JavaScript. Have your server set them with HttpOnly; Secure; SameSite=Lax. A token readable by document.cookie can be stolen by any XSS bug.
- Use Secure on HTTPS sites so cookies are never sent over plain HTTP.
- Set SameSite explicitly. Lax is a good default and helps against CSRF; only use None when a cookie must be sent in cross-site requests.
- Consider the __Host- prefix. A cookie named __Host-session is only accepted with Secure, path=/ and no domain, which stops subdomains from overwriting it.
- Use short lifetimes for anything sensitive, and don't store personal data you don't need.
MDN's guide to HTTP cookies covers the server side in more depth.
FAQs
How do I set a cookie in JavaScript?
Assign a string to document.cookie: document.cookie = "username=JohnDoe; max-age=86400; path=/". Each assignment sets one cookie; add attributes after semicolons.
How do I read a cookie in JavaScript?
Read document.cookie and split it on "; ", then split each pair on its first = — the getCookie function above does this. In newer browsers, await cookieStore.get("name") returns the cookie as an object.
How do I delete a cookie in JavaScript?
Set it again with max-age=0 and the same path and domain it was created with: document.cookie = "username=; max-age=0; path=/".
Can JavaScript read HttpOnly cookies?
No. HttpOnly cookies are sent to the server but never appear in document.cookie or cookieStore. That is the point of the flag.
What happens if a cookie has no expiration date?
It is a session cookie and is removed when the browsing session ends. Browsers that restore your previous session on startup may keep session cookies across restarts.
How long can a cookie last?
Until its max-age or expires time, but Chrome caps every cookie at 400 days. Users can also clear cookies at any time.
How big can a cookie be?
The name and value together can be up to 4096 bytes. Browsers also limit how many cookies one domain can store (at least 50 per domain by the spec).
Are cookies shared across websites?
A page can only read cookies for its own site through document.cookie. Cookies set by embedded third-party content ("third-party cookies") belong to that third party, and browsers increasingly restrict or partition them.
What is the SameSite attribute?
It controls whether a cookie is sent on requests that come from other sites. Strict never sends it cross-site, Lax sends it on top-level navigations such as clicking a link, and None always sends it (Chrome and Firefox also require Secure).
Should I use cookies or localStorage?
Use cookies when the server needs the value on each request, such as a session or consent choice. Use localStorage for larger data that only your JavaScript reads.
Related Articles
View allAbout Muhaymin Bin Mehmood
Front-end Developer skilled in the MERN stack, experienced in web and mobile development. Proficient in React.js, Node.js, and Express.js, with a focus on client interactions, sales support, and high-performance applications.




