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

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 Secure attribute must also be set when using SameSite=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.

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 Secure attribute
  • Be set from an HTTPS origin
  • Omit the Domain attribute
  • 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.

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:

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

Last updated: March 11, 2026