The HTTP protocol remembers nothing: every request arrives as if it were the first. The cookie was invented to fill that gap, and it still carries the sign-in state of most websites.
Its JavaScript interface was never modernized. It comes down to a single property, read and written in a frankly unusual way.
Definition
A cookie is a small named value the browser keeps for a domain and sends back automatically in the header of every request to that domain. On the page side, document.cookie exposes the ones that are not reserved for the server.
document.cookie = "theme=dark; Max-Age=31536000; Path=/; SameSite=Lax";
console.log(document.cookie);
// "consent=1; theme=dark"
const read = Object.fromEntries(
document.cookie.split("; ").map((pair) => {
const i = pair.indexOf("=");
return [pair.slice(0, i), pair.slice(i + 1)];
})
);
console.log(read.theme); // "dark"Reading returns a single string, without the attributes, and writing only adds one cookie at a time: assigning the property does not wipe the others. A value holding a semicolon or a space has to go through encodeURIComponent.
The attributes that matter
Everything after the first semicolon configures the cookie. The table lists them across two columns: the attribute and what it changes.
| Attribute | What it changes |
|---|---|
Max-Age, Expires | The lifetime. Without them the cookie dies when the browser closes |
Path | Which paths of the site will receive the cookie |
Domain | Whether subdomains receive it too |
Secure | Restricts sending to encrypted connections |
SameSite | Whether it is sent when arriving from another site |
HttpOnly | Total invisibility to the scripts of the page |
Deleting a cookie means rewriting it with a zero lifetime, repeating exactly the same Path and Domain: document.cookie = "theme=; Max-Age=0; Path=/". A different path leaves the old cookie untouched.
The last attribute in the table is the one that protects a session. An HttpOnly cookie can only be set by the server, and no script can read it, not even one injected through a vulnerability. That is what sets it apart from a token kept in localStorage.
What each cookie costs
Unlike the other browser storage spaces, a cookie travels. It leaves with every request to its domain, images and files included, which makes it a poor place for bulky data.
- Around four kilobytes per cookie, attributes included.
- A per-domain limit on how many cookies are kept.
- A permanent round trip: a hundred useless bytes multiplied by every request a page makes.
Frequently asked questions
Why does my cookie not show up in document.cookie?
Three causes cover nearly every case. The cookie carries the HttpOnly attribute, in which case it is invisible by design. Its Path or Domain does not match the current page. Or it is marked Secure while the page is served without encryption.
Cookie or localStorage?
One criterion settles it: does the server need the value? If it does, the cookie wins, since it travels on its own with every request. If it does not, localStorage avoids weighing down the traffic and offers far more room.
Is a consent banner always required?
Not for every cookie. European rules exempt the ones strictly necessary for the requested service, such as keeping a session open or holding a shopping cart. Analytics and advertising, on the other hand, require consent collected before anything is stored. Any doubt belongs with the competent authority, not in the code.