HTTP Cookies
An HTTP cookie is a small piece of data sent by a server to the client through the Set-Cookie response header. The browser stores the cookie and sends the value back on subsequent requests using the Cookie request header. This mechanism enables state management in an otherwise stateless protocol, supporting Authentication, user preferences, and tracking across HTTP sessions.
Baseline: Widely available
Supported in all major browsers. webstatus.dev
Usage
When a server needs to associate state with a client, the server includes one or more Set-Cookie headers in the response. Each header sets a single cookie consisting of a name-value pair and optional attributes controlling scope, lifetime, and security.
Cookies serve three primary purposes:
Session management stores login tokens, shopping carts, and other server-side state identifiers. Authentication cookies allow a logged-in state to persist across requests without re-authenticating each time.
Personalization stores user preferences such as language, theme, or layout settings. A dark mode preference, for example, persists between sessions so the server renders the correct stylesheet on each visit.
Tracking builds browsing profiles across pages or sites. Analytics and advertising platforms rely on cookies to correlate activity across multiple requests.
How cookies work
The server sends a Set-Cookie header in the response. The browser stores the cookie and attaches the cookie to every subsequent request to the same origin using the Cookie header. Multiple cookies are separated by semicolons in the Cookie header.
Each Set-Cookie header sets exactly one cookie. To set multiple cookies, the server includes multiple Set-Cookie headers in a single response.
Set-Cookie: theme=dark
Set-Cookie: lang=en
The browser then sends both on the next request:
Cookie: theme=dark; lang=en
Cookie attributes
Attributes follow the name-value pair in a Set-Cookie header, separated by semicolons. Attributes control when, where, and how the browser sends the cookie.
Expires
The Expires attribute sets an absolute expiration
date in HTTP-date format.
After this date, the browser deletes the cookie.
Set-Cookie: sid=abc123; Expires=Sun, 01 Jan 2028 12:00:00 GMT
Client-relative expiration
Expiry dates are relative to the client clock, not the server. Clock skew between server and client affects the actual lifetime.
Max-Age
The Max-Age attribute sets the cookie lifetime
in seconds from the moment the browser receives
the response. A value of zero or negative deletes
the cookie immediately.
Set-Cookie: sid=abc123; Max-Age=3600
When both Expires and Max-Age are present,
Max-Age takes precedence. When neither is set,
the cookie is a session cookie and the browser
deletes the cookie when the session ends.
400-day cookie lifetime cap
The updated cookie specification sets a
recommended upper bound of 400 days (34560000
seconds) for both Max-Age and Expires.
Chromium-based browsers enforce this cap.
Cookies set beyond this limit are clamped to
400 days, allowing sites visited roughly once
a year to maintain state while preventing
indefinite persistence.
Domain
The Domain attribute specifies which hosts
receive the cookie. When omitted, the cookie is
sent only to the exact host, excluding
subdomains. Setting Domain=example.re makes the
cookie available to example.re and all its
subdomains like staging.example.re.
Set-Cookie: sid=abc123; Domain=example.re
Domain scope restriction
A server at staging.example.re is allowed to
set Domain=example.re (its parent). Setting
Domain=news.example.re (a sibling) causes
the browser to reject the cookie.
Path
The Path attribute restricts the cookie to
requests whose URL path starts with the
specified
value. A cookie set with Path=/news is sent for
/news, /news/, and /news/current/world but
not for / or /oldnews.
Set-Cookie: sid=abc123; Path=/news
| Path | Sent? |
|---|---|
/news or /news/ |
Yes |
/news/current |
Yes |
/news/current/world |
Yes |
/ |
No |
/oldnews |
No |
Secure
The Secure attribute instructs the browser to
send the cookie only over HTTPS
connections. Cookies without this attribute are
transmitted over both HTTP and HTTPS.
HttpOnly
The HttpOnly attribute prevents client-side
JavaScript from accessing the cookie through
document.cookie. This mitigates cross-site
scripting (XSS) attacks attempting to steal
session tokens.
SameSite
The SameSite attribute controls whether the
browser sends the cookie on cross-site requests,
providing protection against cross-site request
forgery (CSRF).
Lax (default): The cookie is sent on top-level navigations (clicking a link, entering a URL) using safe methods like GET and HEAD. The cookie is withheld on cross-site subrequests such as image loads or iframe requests.
Strict: The cookie is sent only when the request originates from the same site. No cross-site requests include the cookie, regardless of method or navigation type.
None: The cookie is sent on all cross-site requests. The
Secureattribute must also be set when usingSameSite=None.
When the SameSite attribute is omitted or set
to an unrecognized value, browsers apply Lax
enforcement by default. Some browsers briefly
apply a "Lax-allowing-unsafe" mode for newly set
cookies, permitting cross-site top-level
POST requests for a short window after
creation. This transitional behavior helps
existing login flows and payment redirects
complete before full Lax enforcement takes effect.
Set-Cookie: sid=abc123; SameSite=Lax; Secure
Partitioned (CHIPS)
The Partitioned attribute opts the cookie into
partitioned storage. A partitioned cookie is keyed
by both the cookie domain and the top-level site
of creation. This prevents a third-party
service from correlating activity across unrelated
top-level sites.
Set-Cookie: __Host-embed=val; SameSite=None; Secure; Path=/; Partitioned
Partitioned cookies require Secure and work in
combination with SameSite=None.
Updated cookie specification
The defining cookie specification (6265bis) is
in the RFC Editor Queue and replaces the
original. Key changes: SameSite=Lax becomes
the formal default, cookie name+value size is
capped at 4096 bytes with each attribute
capped at 1024 bytes, cookie lifetimes are
bounded to 400 days, name prefix matching
becomes case-insensitive, and Secure is
required for SameSite=None. The Partitioned
attribute (CHIPS) is defined in a companion
specification from the Privacy Community Group.
Persistence
A session cookie has no Expires or Max-Age
attribute. The browser deletes the cookie when the
session ends, typically when the browser closes. Some
browsers restore session cookies when using session
restore features.
A permanent cookie includes an Expires or
Max-Age attribute. The browser persists the cookie
to disk and sends the cookie on future requests
until the
expiration date passes.
Cookie prefixes
Two name prefixes add extra validation rules
the browser enforces at cookie-setting time.
Browsers match these prefixes case-insensitively,
so __HOST-SID and __host-sid both trigger
the same enforcement.
__Host-
A cookie with the __Host- prefix must:
- Include the
Secureattribute - Be set from an HTTPS origin
- Omit the
Domainattribute - Set
Path=/
These constraints domain-lock the cookie to the exact host, with no subdomain access.
Set-Cookie: __Host-sid=abc; Secure; Path=/
__Secure-
A cookie with the __Secure- prefix must include
the Secure attribute and originate from an
HTTPS connection. Unlike __Host-, a
Domain attribute is permitted.
Set-Cookie: __Secure-sid=abc; Secure; Domain=example.re
First-party and third-party cookies
A first-party cookie belongs to the domain visible in the browser address bar. A third-party cookie belongs to a different domain, typically an embedded resource like an advertising tracker or analytics pixel loaded in an iframe or through a cross-site request.
Third-party cookies enable cross-site tracking, which raises privacy concerns. Safari and Firefox block third-party cookies by default. Chrome retains third-party cookie support but provides user controls in privacy settings, and encourages migration to partitioned cookies (CHIPS) for legitimate cross-site use cases.
Declining third-party cookie support
Third-party cookies are blocked by default in Safari (Intelligent Tracking Prevention) and Firefox (Enhanced Tracking Protection). Chrome reversed its planned deprecation but continues to develop Privacy Sandbox APIs as alternatives. New cross-site integrations benefit from designing around partitioned cookies or server-side approaches from the start.
Security
Cross-site request forgery (CSRF)
CSRF attacks exploit browsers automatically
attaching cookies to requests. A
malicious site triggers a request to a target
origin, and the browser includes the target's
cookies. The SameSite attribute is the primary
defense: Lax blocks most CSRF vectors by
withholding cookies on cross-site subrequests.
Strict provides the strongest protection.
Server-side CSRF tokens add a second layer of
defense.
Cross-site scripting (XSS)
An XSS vulnerability allows an attacker to run
JavaScript in the context of the target origin.
Without HttpOnly, the script reads cookies via
document.cookie and exfiltrates session tokens.
Setting HttpOnly on session cookies blocks this
vector. Content Security Policy
(CSP) and input
sanitization address the root cause.
Cookie theft over plaintext HTTP
Cookies without the Secure attribute are sent
over unencrypted HTTP connections. A network
attacker observing traffic reads the cookie value
in transit. The Secure flag, combined with
HSTS, ensures cookies travel only over
encrypted connections.
Performance
Cookies are sent with every HTTP request to the matching domain and path, adding bytes to each request. Large or numerous cookies increase request overhead, especially on connections with limited bandwidth.
The updated cookie specification enforces strict size limits. Browsers reject any cookie whose name and value combined exceed 4096 bytes. Each individual attribute value is capped at 1024 bytes. These normative limits replace the looser recommendations in the original specification and reduce interoperability differences between browsers. Keeping cookie values small and limiting the number of cookies per domain (at least 50 per domain are supported) reduces overhead.
SEO and cookie overhead
Googlebot sends cookies when set by the origin. Large cookies on asset domains increase the size of every resource request during rendering. Using a separate cookieless domain for static assets (images, CSS, JavaScript) avoids this overhead during both user browsing and search engine crawling.
Regulations
Privacy regulations govern how sites collect and use cookie data:
- The General Data Protection Regulation (GDPR) requires informed consent before setting non-essential cookies for EU visitors.
- The California Consumer Privacy Act (CCPA) gives California residents the right to opt out of data collection through cookies.
These regulations require clear disclosure of cookie purposes and provide users control over non-essential cookie storage.
Example
A server sets several cookies with different
attributes. The theme and lang cookies are
session cookies deleted when the browser closes.
The sid cookie is a secure, HTTP-only session
token with a one-hour lifetime. The prefs cookie
persists for 30 days.
Response
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 4821
Set-Cookie: theme=dark
Set-Cookie: lang=en
Set-Cookie: sid=abc123; Max-Age=3600; Secure; HttpOnly; SameSite=Lax
Set-Cookie: prefs=compact; Max-Age=2592000; Secure; Path=/
Shortly after, the browser sends all four cookies
back. The sid cookie value is opaque to
JavaScript because of the HttpOnly flag, but the
browser still includes the value in the request
header.
Request (shortly after)
GET / HTTP/1.1
Host: www.example.re
Cookie: theme=dark; lang=en; sid=abc123; prefs=compact
After one hour, the sid cookie expires. The
browser stops sending the expired cookie.
Request (more than one hour later)
GET / HTTP/1.1
Host: www.example.re
Cookie: theme=dark; lang=en; prefs=compact
Takeaway
HTTP cookies provide state management for the
stateless HTTP protocol. Servers set cookies through
Set-Cookie headers with attributes
controlling scope, lifetime, and security. The
SameSite, Secure, and HttpOnly attributes are
essential for protecting cookies against CSRF, XSS,
and network interception. Cookie prefixes
(__Host-, __Secure-) enforce additional
constraints at the browser level. Partitioned
cookies (CHIPS) offer a privacy-preserving
alternative for legitimate cross-site use cases as
third-party cookie support continues to narrow.
See also
- RFC 6265: HTTP State Management Mechanism
- RFC 6265bis (in RFC Editor Queue): Cookies: HTTP State Management Mechanism
- CHIPS Explainer: Cookies Having Independent Partitioned State
- Set-Cookie
- Cookie
- HTTP sessions
- Cross-Origin Resource Sharing (CORS)
- HTTP authentication
- HSTS
- HTTPS
- HTTP headers