---
title: Cookies
description: HTTP cookies are small data the browser stores for a website. The server sets them with Set-Cookie; the browser sends them back on later requests. HttpOnly, Secure, and SameSite control who can read them and when they are sent.
tokens: ~786
---

# Cookies

HTTP is stateless: each request stands alone, with no built-in memory of earlier ones. Cookies are one way the browser stores data for a site, next to `localStorage`, `sessionStorage`, and IndexedDB, and the usual way to implement a **session**: the server sets an identifier, and the browser sends it back on later matching requests.

## What a cookie is

A cookie is a name–value pair the browser keeps for a site, for example `session=abc`. JavaScript reads the cookies it is allowed to see via `document.cookie`, which returns a single string of `name=value` pairs joined by `; `. Setting `document.cookie` adds or updates one cookie; it does not replace the whole jar.

There is no delete API. To remove a cookie, set it again with the same `name`, `Path`, and `Domain`, and an `Expires` date in the past (or `Max-Age=0`).

Browsers cap a cookie at about **4 KB** (name, value, and attributes together) and limit how many cookies a domain may store. Oversized cookies are dropped.

```javascript
document.cookie; // "theme=dark; locale=en"
document.cookie = "theme=light; Path=/; Max-Age=86400";
document.cookie = "theme=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT";
```

`document.cookie` never sees [HttpOnly](#httponly-secure-and-signed-cookies) cookies.

## Attributes

| Attribute | Role |
| --- | --- |
| `Domain` | Hosts that receive the cookie. Default is the current host only (no subdomains). |
| `Path` | URL path prefix that must match. Default is the path of the response that set it. |
| `Expires` / `Max-Age` | Lifetime. With neither, the cookie is a **session cookie** and goes away when the browser session ends. `Max-Age` (seconds) wins if both are set. |
| `Secure` | Sent only over HTTPS. |
| `HttpOnly` | Hidden from JavaScript (`document.cookie` and `CookieStore`). |
| `SameSite` | Whether the cookie goes on cross-site requests: `Strict`, `Lax` (default in modern browsers), or `None` (requires `Secure`). See [CSRF](/docs/web/security/csrf). |

The browser sends matching cookies on later requests in the `Cookie` request header.

## `Set-Cookie` from the server

The server asks the browser to store a cookie with the `Set-Cookie` response header. One header per cookie.

```http
HTTP/1.1 200 OK
Set-Cookie: session=abc; Path=/; HttpOnly; Secure; SameSite=Lax
```

The browser then attaches it:

```http
GET /account HTTP/1.1
Host: app.example.com
Cookie: session=abc
```

`Set-Cookie` is ignored on a CORS response whose `Access-Control-Allow-Origin` is `*`. See [CORS](/docs/web/http/cors#credentials-and-).

### HttpOnly, Secure, and signed cookies

Session identifiers belong in **HttpOnly** + **Secure** cookies so [XSS](/docs/web/security/xss) cannot read them via `document.cookie`, and they never travel on plain HTTP. Theft and fixation are covered in [Session Attacks](/docs/web/security/session-attacks).

**Signing** is a server-side check, not a browser attribute. The server stores `value.hmac` (or similar) and rejects the cookie if the client changed the value. Signing detects tampering; it does not hide the value. Encrypt the payload if the contents must stay secret from the browser owner.