A cookie is a small piece of text a website asks your browser to store and hand back on every later request. It is how a site that forgets you between clicks can still keep you logged in, remember your settings and hold on to your basket.
Why the web needs cookies
HTTP, the protocol your browser uses to talk to websites, is stateless. Each request stands on its own: when the server answers one, it keeps no built-in memory of who asked. Load the home page, then the basket page, and as far as HTTP is concerned those are two strangers knocking on the door.
That is fine for a page that looks the same to everyone. It breaks down the moment a site needs to know it is still you: after you sign in, when you pick dark mode, or when you add something to a basket and move on to the next page.
Cookies fill that gap. The server gives your browser a small note, the browser keeps it, and from then on it attaches the note to every request it sends to that site. The server reads the note and knows who it is dealing with.
How a cookie travels
A cookie moves in two HTTP headers, one in each direction:
- The server sends
Set-Cookiein a response. That tells the browser: store this name and value. - On every later request to the same site, the browser sends
Cookiewith the stored name and value in it.
The browser does the second part on its own. Your page's code doesn't have to remember to attach anything, which is exactly what makes cookies convenient for staying logged in.
Here is the whole round trip, from a first visit to a return visit:
A cookie set on one visit and sent back on the next
Step 1 of 8: On your first visit the request carries no cookie, so the server has no idea who you are.
The same exchange as raw headers
This is what the two requests look like on the wire. First, the response to your first visit:
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: sid=abc123; Path=/; HttpOnly; SecureThen every later request the browser makes to that site:
GET /basket HTTP/1.1
Host: shop.example
Cookie: sid=abc123Notice what the cookie holds: a session id, not the basket itself. The server keeps the real data in its own store and uses the id as the key to find it. That is the usual pattern for anything sensitive or large, because cookies are small (browsers only promise about 4 KB each) and every byte travels with every request.
What cookies are used for
Most cookies fall into three jobs:
- Logins and sessions. After you sign in, the server sets a session cookie so every page you open knows it is still you.
- Preferences. A language, a theme, whether you closed a banner. Small values that change how the site looks for you.
- Shopping baskets. A cookie ties your basket to you as you browse, even before you have an account.
There is a fourth use you meet as a user more than as a developer: tracking. That comes up under third-party cookies below.
The attributes that shape a cookie
A Set-Cookie header is more than a name and a value. The attributes after it decide how long the cookie lives, where it is sent and who can read it.
How long it lives
- With no
ExpiresorMax-Age, it is a session cookie: the browser drops it when the browsing session ends. Max-Age=3600keeps it for an hour.Expiresdoes the same with a fixed date.- To delete a cookie, the server sets it again with
Max-Age=0.
Where it is sent
DomainandPathlimit which URLs get the cookie. LeaveDomainout and only the exact host that set it receives it.Securemeans the cookie is only sent over HTTPS, never plain HTTP.SameSitecontrols whether it is sent on requests that start on another site.Strictnever sends it cross-site,Laxsends it when you follow a link to the site, andNonealways sends it (and must be paired withSecure).
Who can read it
HttpOnlyhides the cookie from JavaScript. The browser still sends it with requests, butdocument.cookiecan't see it.
Here is a server setting a sensible login cookie, in Express:
res.cookie("sid", sessionId, {
httpOnly: true, // no JavaScript access
secure: true, // HTTPS only
sameSite: "lax", // not on most cross-site requests
maxAge: 1000 * 60 * 60 * 24 // one day, in ms
});And the browser side, for a harmless preference that JavaScript is allowed to read:
document.cookie = "theme=dark; Max-Age=31536000; Path=/";
console.log(document.cookie);
// "theme=dark" (HttpOnly cookies never show)document.cookie is an odd API: assigning to it adds or updates one cookie rather than replacing them all, and reading it gives you one long string of every visible name=value pair.
Cookies and security
Because the browser sends cookies automatically, a session cookie is as good as a password while it is valid. Anyone who gets hold of it can act as you. Three attributes do most of the defending:
HttpOnlystops an injected script (cross-site scripting, or XSS) from reading the session id and sending it somewhere else.Securekeeps the cookie off unencrypted connections, where anyone on the network could read it.SameSitelimits cross-site request forgery (CSRF): a page on another site tricking your browser into sending a request, with your cookie attached, to a site you are logged in to.
Some browsers, Chrome among them, treat a cookie with no SameSite as Lax, but not all do. Set it yourself rather than relying on the default.
Cookies or local storage?
Browsers also offer localStorage, and the two are often confused:
| Cookies | localStorage | |
|---|---|---|
| Sent to the server | On every request | Never |
| Readable by JavaScript | Unless HttpOnly | Always |
| Typical size | About 4 KB each | A few MB per site |
Use a cookie when the server needs the value on each request, as it does with a session. Use localStorage for data only the page's own code needs, such as a draft or a cached setting. Putting a login token in localStorage means any script on the page can read it, which is why many sites keep session ids in HttpOnly cookies instead.
First-party and third-party cookies
A first-party cookie belongs to the site in your address bar. A third-party cookie is set by a different domain whose content is embedded in the page, such as an advert or a tracking script. Because the same third party is embedded across many sites, its cookie can follow you from one to the next and build a picture of your browsing.
That is why cookie consent banners exist, and why many browsers now block or restrict third-party cookies by default. First-party cookies for logins, preferences and baskets are not affected in the same way.
Common mistakes
- Storing real data in the cookie. Keep a session id in it and the data on the server. A cookie can be read and edited on the user's machine, so never trust its contents without checking them.
- Forgetting
HttpOnlyandSecureon session cookies. Without them, a single XSS bug or an HTTP page can leak every session. - Letting cookies grow. Every cookie for a site rides along with every request, images and scripts included. Ten large cookies slow down every page.
- Logging out on the client only. Deleting the cookie in the browser isn't enough: the server has to end the session too, or a copied cookie keeps working.
Key takeaways
- A cookie is a small piece of data stored in your browser and sent back to the same site on each visit.
- The server sets it with
Set-Cookie; the browser returns it withCookie, automatically. - Cookies let a stateless protocol remember you: logins, preferences and baskets.
- Keep a session id in the cookie and the real data on the server.
- Protect session cookies with
HttpOnly,SecureandSameSite.