How to Manage Cookies in JS: Complete Tutorial
Learn how to create, read, update, configure, and delete browser cookies with JavaScript. Covers path, domain, expiration, Secure, and SameSite attributes.
Cookies are small pieces of data the browser stores and sends to the server with every HTTP request. Unlike localStorage, cookies travel to the server automatically, making them the right choice for session tokens, authentication, and any data the backend needs to read.
In JavaScript, you manage cookies through the document.cookie property. It is not a normal object.
Reading returns all cookies at once. Writing sets one cookie at a time.
document.cookie = "theme=dark; path=/; max-age=86400";
console.log(document.cookie);This cookie named "theme" is set with a one-day lifetime and available on every page path. Here is what document.cookie contains after the assignment:
theme=darkThis sets a cookie named "theme" with the value "dark", available on every page, lasting 86,400 seconds (one day). It never touches other cookies on the same origin.
Setting a cookie
The basic syntax for creating a cookie assigns a name=value pair directly to document.cookie, and any attributes you want to add come after the value, separated by semicolons. Here is what a minimal cookie assignment looks like:
document.cookie = "username=Rune; path=/; max-age=604800";This creates a cookie named "username" that lives for one week. Writing to document.cookie does not overwrite other cookies, it only adds or updates the one you name.
The attributes control where, when, and how the cookie is used.
Cookie attributes explained
The semicolon-separated parts after the value define the cookie's behavior. Here is what each attribute controls:
| Attribute | Format | What it does |
|---|---|---|
| path | path=/ | Limits the cookie to a URL path. path=/admin means the cookie is only sent on /admin pages |
| domain | domain=example.com | Sets which domain and its subdomains can access the cookie |
| expires | expires=Thu, 01 Jan 2032 00:00:00 UTC | Sets an absolute expiration date in UTC |
| max-age | max-age=3600 | Sets the cookie lifetime in seconds from now |
| Secure | Secure | Cookie is only sent over HTTPS connections |
| SameSite | SameSite=Strict | Controls cross-site behavior: Strict, Lax, or None |
You do not need every attribute on every cookie. A typical preference cookie looks like this:
document.cookie =
"fontSize=large; path=/; max-age=2592000; Secure; SameSite=Lax";This cookie lasts 30 days, is only sent over HTTPS, and uses SameSite=Lax, the modern default that blocks cookies on cross-site requests while allowing top-level navigations.
Session cookies vs persistent cookies
If you omit both expires and max-age, the cookie becomes a session cookie that disappears when the user closes the browser. Use session cookies for temporary state like a form wizard that should not survive a browser restart.
To make a cookie persistent, set max-age in seconds:
const oneYearInSeconds = 365 * 24 * 60 * 60;
document.cookie = `returningUser=true; path=/; max-age=${oneYearInSeconds}`;Secure and SameSite
The Secure flag ensures the cookie is only sent over HTTPS. During local development on http://localhost, browsers usually skip the Secure requirement, but production deployments on https:// should always include it.
SameSite controls whether the cookie is sent when the request originates from a different site. Strict blocks all cross-site usage entirely.
Lax, the browser default, allows top-level navigations like clicking a link but blocks cookies in iframes. None sends cookies on all cross-site requests, but requires Secure.
A reusable cookie utility
Wrapping cookie operations in a small object keeps your code clean and avoids repeated formatting logic. Start with the set and get methods:
const cookies = {
set(name, value, days = 7, path = "/") {
const maxAge = days * 24 * 60 * 60;
document.cookie =
`${encodeURIComponent(name)}=${encodeURIComponent(value)}; path=${path}; max-age=${maxAge}; SameSite=Lax`;
},
get(name) {
const match = document.cookie.match(
new RegExp(`(?:^|; )${name}=([^;]*)`)
);
return match ? decodeURIComponent(match[1]) : null;
},
};The set method constructs the full cookie string by encoding the name and value, setting the path, computing max-age from the days parameter, and appending SameSite=Lax for security. The get method searches document.cookie with a regex that matches the cookie name at the start of the string or right after a semicolon separator.
Add a remove method that expires the cookie immediately:
cookies.remove = function (name, path = "/") {
document.cookie =
`${encodeURIComponent(name)}=; path=${path}; max-age=0`;
};Setting max-age to zero tells the browser the cookie has already expired. Now all three methods are ready to use:
cookies.set("theme", "dark");
console.log(cookies.get("theme"));
cookies.remove("theme");
console.log(cookies.get("theme"));Setting a cookie, reading it back immediately, and then removing it produces the expected results in this three-step sequence. After the remove call runs, get returns null because the cookie no longer exists:
dark
nullUsing encodeURIComponent on names and values prevents problems with spaces, semicolons, and special characters. The remove method sets max-age=0, telling the browser to expire the cookie immediately.
When to use cookies vs localStorage
Cookies and localStorage solve different problems. Cookies are sent with every HTTP request, so the server sees them automatically. localStorage is client-only.
Use cookies when the server needs the data, you need server-controlled expiration, or you need the HttpOnly flag for security-sensitive tokens. Use localStorage when the data only matters on the client side, you do not want the data sent to the server on every request, or you need more than 4 KB of storage per value.
Each storage mechanism has its tradeoffs. For a detailed side-by-side comparison of all three options, see the dedicated comparison article on cookies, localStorage, and sessionStorage.
Common mistakes
- Not encoding cookie values. A value containing a semicolon or space breaks the attribute parsing.
- Setting HttpOnly from JavaScript. HttpOnly is a server-side flag. Adding it to document.cookie has no effect.
- Forgetting the path in deletions. Match the original cookie's path exactly when removing.
- Setting cookies too large. Individual cookies are limited to about 4 KB.
- Omitting Secure on SameSite=None cookies. Browsers require Secure with SameSite=None.
Related articles
- Parsing and Deleting Browser Cookies with JS -- detailed guide on reading and removing cookies
- JS localStorage API Guide: A Complete Tutorial -- persistent client-side key-value storage
- JS sessionStorage API Guide: Complete Tutorial -- temporary storage scoped to a single tab
Quick reference
| Operation | Code |
|---|---|
| Set a cookie | document.cookie = "name=value; path=/; max-age=3600" |
| Session cookie | Omit max-age and expires |
| Read a cookie | Parse document.cookie with a regex or split utility |
| Delete a cookie | Set max-age=0 with matching path |
| Encode special chars | Use encodeURIComponent on name and value |
Rune AI
Key Insights
- Set a cookie by assigning a name=value string to document.cookie with optional semicolon-separated attributes.
- Session cookies with no expiration disappear when the browser closes.
- HttpOnly cookies cannot be read or modified by JavaScript at all.
- Use encodeURIComponent on names and values to handle special characters.
- Build a small cookie utility object to avoid repeating formatting logic.
Frequently Asked Questions
Why does my cookie not appear in document.cookie after setting it?
How long does a cookie last without an expiration?
Can I set a cookie for a different domain?
What is the maximum size of a cookie?
Conclusion
Managing cookies in JavaScript means knowing how to format the document.cookie assignment string correctly. The cookie value comes first, then semicolon-separated attributes. Once you wrap the common operations in a small utility object, working with cookies is straightforward.
More in this topic
Using Decorators for Logging in JS Architecture
Learn how JavaScript decorators wrap class methods to add logging without touching the original code, including setup with Babel and how execution order works.
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.