Deciding when a cookie crosses sites
The SameSite cookie attribute controls whether a cookie accompanies requests
that originate from a different site, which is the core defence against
cross-site request forgery (CSRF) and a key lever in third-party cookie
deprecation. This reference covers the three values and shows, per request
type, whether the cookie is sent.
How it works
The browser classifies each request as same-site or cross-site relative to the cookie’s domain, then applies the attribute:
Set-Cookie: session=abc; SameSite=Lax; Secure; HttpOnly
Set-Cookie: widget=xyz; SameSite=None; Secure
Strict sends the cookie only on same-site requests. Lax (the default) adds
one exception — top-level cross-site navigations using a safe method, such as
clicking a link. None sends the cookie on all cross-site requests but is
rejected unless paired with Secure. Even None; Secure cookies are now
frequently blocked as part of third-party cookie phase-out.
The sending matrix
| Request type | Strict | Lax (default) | None + Secure |
|---|---|---|---|
| Same-site (any method) | Sent | Sent | Sent |
| Cross-site top-level GET navigation (link click) | Not sent | Sent | Sent |
| Cross-site top-level POST (form submission) | Not sent | Not sent | Sent |
| Cross-site iframe load | Not sent | Not sent | Sent |
| Cross-site subresource (img, script, CSS) | Not sent | Not sent | Sent |
| Cross-site background fetch / XHR | Not sent | Not sent | Sent |
Understanding this matrix is the core of using SameSite correctly. The most important row is “cross-site top-level GET navigation” — Lax allows the cookie here (so users arriving from a link stay logged in), while Strict does not (so they appear logged out until they complete a same-site navigation).
Practical decision guide
Use Strict for session cookies on high-sensitivity applications — admin consoles, banking, healthcare portals — where an authenticated GET request triggered from another page would be dangerous even without a method change.
Use Lax (or leave it unset) for standard authenticated web applications. Most session cookies should be here. Users arriving via link stay logged in; cross-site POST forms (CSRF vectors) do not carry the cookie.
Use None; Secure when a cookie genuinely needs to work across sites — embedded widgets, OAuth callbacks that traverse origins, third-party analytics. Be aware that this mode is increasingly blocked by browsers as part of third-party cookie phase-out, and plan for alternatives.
Third-party cookie deprecation and what to do
Chrome’s multi-year effort to remove third-party cookie support, combined with existing blocking in Safari and Firefox, means SameSite=None; Secure cookies are increasingly unavailable for many use cases. Alternatives depending on your scenario:
- CHIPS (Partitioned attribute): The cookie is scoped to the top-level site — so an embedded
widget.example.comcookie is partitioned separately for each site that embeds it. Supported in Chrome; usePartitionedalongsideSameSite=None; Secure. - Storage Access API: Lets embedded frames request user-granted access to unpartitioned cookies via a browser permission prompt.
- FedCM (Federated Credential Management): For federated identity flows replacing cookie-based cross-site SSO.
- Server-side approaches: For analytics and attribution, first-party server-side event collection avoids the third-party cookie issue entirely.
Tips and notes
- Default to
Lax; reserveStrictfor the most sensitive session cookies. SameSite=NonewithoutSecureis rejected — always pair them.- For embedded cross-site cookies, consider CHIPS (
Partitioned) or the Storage Access API. Laxstill permits the cookie on top-level GET navigations, so it is not full CSRF immunity — also use CSRF tokens.- A subresource (image, script, fetch) to your own site from a third-party page is cross-site and follows these rules.