SameSite cookies: Lax vs Strict vs None, tested in Chrome

We set one cookie per SameSite value and sent every common kind of cross-site request at it. This is what arrived.

1. What Chrome sent (request from another site)

Request from another siteLaxStrictNone; SecureNo SameSite
Link click (top-level GET)SentNot sentSentSent
Form POSTNot sentNot sentSentSent if set < 2 min ago, then not sent
fetch() with credentials: 'include'Not sentNot sentSentNot sent
iframeNot sentNot sentSentNot sent
ImageNot sentNot sentSentNot sent

Visiting the cookie's own site directly sent all of them.

2. Three things the table shows

3. Which value to use

Set-Cookie: session=abc123; Path=/; Secure; HttpOnly; SameSite=Lax

"Cross-site" means a different registrable domain (plus scheme), not just a different origin: app.example.com and api.example.com are the same site, so SameSite does not separate them.

Frequently asked questions

What is the default SameSite value?

Lax. In our Chrome test a cookie with no SameSite attribute was stored as Lax and blocked on cross-site fetch, iframe and image requests.

Why is my SameSite=None cookie not set?

It needs Secure. In our test SameSite=None without Secure was rejected outright, while SameSite=None; Secure was stored and sent on every cross-site request.

Is a Lax cookie sent when the user clicks a link from another site?

Yes, on top-level GET navigation. Strict cookies were not sent on that click.

Does SameSite stop cross-site form POSTs?

Lax and Strict cookies were not sent on a cross-site POST. A cookie with no SameSite attribute was still sent during its first 2 minutes.

Written with AI assistance. Measured on 2026-10-01 in Chromium 153: site 127.0.0.1:8982 set one cookie per SameSite value, then a page on a different site (localhost:8981) made a credentialed fetch(), loaded an iframe and an image, followed a link and submitted a POST form to it, and the server logged the Cookie header of each request. Chrome treats 127.0.0.1 as a secure context, which is why the Secure cookie was stored over plain HTTP here; on a real domain it needs HTTPS. PlainHeaders is our extension; the other methods are free.