Skip to content

The cookie and identity layer: SameSite, partitioning, and the third-party-cookie death

· 18 min read
Copyright: MIT
Set-Cookie wordmark with SameSite=None and the word None highlighted in orange

A cookie is four bytes of opaque state the server hands you and asks you to hand back. That is the entire mechanism. There is no cryptography in the format, no notion of identity in the spec, nothing that says “this is who you are.” And yet for thirty years the cookie has been the closest thing the web has to a login, a session, a shopping cart, and an advertising dossier all at once. The identity layer of the web was never designed. It accreted on top of a key-value pair invented to keep a Netscape store from having to remember anything.

So how did a stateless-by-design protocol end up running the entire authentication and tracking economy on a string the client is free to lie about? And what happens to that economy when the largest browser vendor on earth spends five years promising to kill the cross-site version of that string, then quietly decides not to? This post follows the cookie from its origin as a server-side amnesia patch, through the RFCs that tried and mostly failed to discipline it, into the SameSite attribute that finally gave servers a say in when their cookies travel, and out the other side into the third-party-cookie phase-out saga that consumed the ad-tech industry from 2020 to 2025 and then reversed. The through-line is a single tension: the cookie carries identity, identity is valuable, and every attempt to constrain it has had to negotiate with the people who profit from it.

1994: a patch for server amnesia

The cookie exists because MCI did not want to store shopping-cart state on its servers. In June 1994 Lou Montulli, an early Netscape engineer, was asked to solve the problem of a virtual shopping cart that survived between page loads without the e-commerce backend holding per-user session memory. The answer was to push that state down to the client. The browser would hold a small token, send it back on every request to the same site, and the server could stay stateless. Montulli wrote the first specification that year with John Giannandrea, and Mosaic Netscape 0.9beta shipped with cookie support on 13 October 1994.

The name came from “magic cookie,” a term Montulli had picked up from an operating-systems course for an opaque token passed between programs. He liked it for aesthetic reasons. The mechanism was deliberately dumb: a Set-Cookie response header on the way out, a Cookie request header on the way back, and an attribute or two governing expiry and which paths the cookie applied to. Montulli filed for a patent in 1995; US Patent 5,774,670 issued on 30 June 1998.

The design had a quiet flaw that nobody fully reckoned with at the time. Nothing about the model restricted a cookie to the site you were actually looking at. A page on news.example could embed an image from ads.example, and that image request carried ads.example’s cookies. The ad server could set a cookie the first time it saw you and read it back on every other site that embedded the same ad network. The shopping-cart token had become a cross-site identifier the moment pages started embedding third-party resources, which was almost immediately. The public noticed slowly; a Financial Times article on 12 February 1996 is usually cited as the first mainstream coverage, and from there the cookie’s reputation never fully recovered.

1997-2011: the RFCs that ran behind the browsers

The standards process spent fifteen years trying to catch up to what Netscape had shipped. RFC 2109 arrived in February 1997, formalising Cookie and Set-Cookie and gesturing at privacy controls around third-party cookies. RFC 2965 followed in October 2000, introducing a parallel Set-Cookie2 header and a versioning scheme that the browsers essentially ignored. Set-Cookie2 was a standards-track ghost. It was implemented thinly, used almost nowhere, and formally deprecated when RFC 6265 superseded both earlier documents in April 2011.

RFC 6265 is the one that matters, because it gave up on prescribing ideal behaviour and instead documented what browsers actually did. Before it, there were at least three competing descriptions of cookies and none of them matched reality. The 6265 approach was archaeological: describe the de-facto Netscape syntax, the real parsing quirks, the security attributes that had crept in over the years. Two of those attributes carry most of the security weight even now. Secure tells the browser to only send the cookie over HTTPS. HttpOnly hides the cookie from JavaScript’s document.cookie, which is the single most effective mitigation against a cross-site-scripting attacker stealing a session token. Neither does anything about the cross-site-identity problem. A cookie marked Secure; HttpOnly is still attached to every cross-site request to its origin, which is exactly the behaviour that powers third-party tracking.

Set-Cookie response header, field by field __Host-SID =31d4d96e407aad42 name (prefix-bound) opaque value — server's to interpret ; Secure ; HttpOnly ; Path=/ ; SameSite=Lax HTTPS-only no JS read scope when does it travel cross-site? The format carries no identity and no integrity. Everything above the line is the server's secret; everything below it is policy. *The Set-Cookie wire format. The value is opaque to the browser, which is why a cookie can be a session id, a JWT, or a tracking pixel's user id with no change to the mechanism.*

The cookie’s two superpowers and its central problem all come from the same fact: the value is opaque. The browser does not know whether 31d4d96e407aad42 is a session handle, a signed token, or a global advertising id, and it does not care. That opacity is what lets the cookie be the universal identity primitive. It is also why the browser cannot reason about privacy at the value level and has to do everything through coarse attributes about scope and transport instead. Every privacy control bolted onto cookies since has been a control on when the cookie travels, never on what it says.

2016-2020: SameSite gives the server a say

The first real lever against cross-site cookie sends came from a 2016 IETF draft by Mike West of Google and Mark Goodwin of Mozilla. The SameSite attribute lets a server declare that a cookie should not ride along on cross-site requests, which both blunts cross-site request forgery and cuts off a class of cross-site information leakage. It updated RFC 6265 and eventually folded into the long-running 6265bis revision. The attribute takes three values, and the precise semantics are worth getting right because almost every explanation of them is slightly wrong.

Strict is the easy one: the cookie is only ever sent on same-site requests. Click a link from an email into your bank and a Strict session cookie will not come along, so you land logged out even though you have a valid session. That breakage is why almost nobody uses Strict for session cookies.

Lax is the interesting value, and the one that became the default. A Lax cookie is sent on same-site requests and on cross-site top-level navigations that use a safe method. The distinction is navigation versus subresource. Clicking a link that takes the whole browser tab to a new site is a top-level navigation, and a Lax cookie rides along, so the bank link from the email works. An <img>, an <iframe>, a fetch(), or a form POST from another origin is a subresource or an unsafe-method request, and the Lax cookie is withheld. That is the sweet spot the designers were aiming at: keep the normal experience of following links between sites while cutting off the silent cross-site requests that CSRF and tracking rely on.

None means the cookie is sent everywhere, same-site and cross-site, exactly like the pre-SameSite world. The standards process attached a condition: a cookie that declares SameSite=None must also be Secure, or the browser ignores it entirely. The cross-site cookie became an explicitly opt-in, HTTPS-only artefact. If you want a tracking cookie or a cross-site embed cookie, you now have to say so out loud in the header.

Is the cookie attached to this request? same-site cross-site, top-level nav, safe method cross-site subresource Strict yes no no Lax yes yes no None (+Secure) yes yes yes *The three SameSite values reduce to one question asked across two request types. Lax is the default because it preserves link-following while killing silent cross-site sends.*

In February 2020 Chrome 80 made the consequential move: cookies with no SameSite attribute would be treated as SameSite=Lax rather than the historical “send everywhere.” Every cross-site cookie that had been quietly relying on the old default now had to declare SameSite=None; Secure or stop working cross-site. This was a default-flip with teeth, and it broke things. Some single-sign-on flows POST credentials across origins as a top-level navigation, and a brand-new Lax cookie would be withheld from exactly that POST. Chrome shipped a deliberately ugly intervention called “Lax + POST” to soften it: a cookie set without SameSite would still be sent on a cross-site top-level POST if it was less than two minutes old. The two-minute window was a heuristic for “this cookie was just minted by a login flow,” and Chrome documented from the start that the intervention was temporary. The rollout itself slipped. Google paused enforcement on 3 April 2020 because of the early pandemic, then resumed on 14 July 2020.

A word of honesty about CSRF, because SameSite is routinely oversold as a complete fix. It is defence in depth, not a substitute for anti-CSRF tokens. Lax still permits cross-site top-level GETs, so any application that performs a state change on a GET is unprotected. Frameworks that support method-override let an attacker send a GET that the server treats as a POST. And SameSite reasons about site, not origin, so a sibling subdomain you do not fully trust counts as same-site. The attribute closed the easiest CSRF holes and made the lazy ones harder, which is genuinely valuable, but a security review that sees SameSite=Lax and stops looking has stopped too early.

2017-2023: the browsers that did not wait for a standard

While Chrome was tuning defaults, Safari and Firefox were doing something more aggressive and on their own schedule. Apple shipped Intelligent Tracking Prevention in 2017 and tightened it in stages until, with Safari 13.1 in March 2020, it blocked all third-party cookies outright, with no interaction-based exceptions. Safari also began capping the lifetime of script-set first-party cookies; client-side document.cookie storage gets clamped to seven days, which broke a generation of analytics scripts that had been hiding first-party tracking ids in JavaScript cookies. The lesson the ecosystem took from ITP was that the browser would treat the cookie’s value as suspect by treating its lifetime as policy.

Firefox went a different way with Total Cookie Protection, on by default since 2022 as part of Enhanced Tracking Protection. Rather than block third-party cookies, Firefox gives each top-level site its own cookie jar. A third party embedded on a.example and on b.example gets a cookie, but the cookie stored under a.example is invisible when the same third party runs inside b.example. The cookie still exists; it just cannot be the same cookie across two different first-party contexts. This is partitioning, and it is the idea that survives the whole saga. Hold onto it.

By 2023 the browser positions had hardened into a split. Safari and Firefox blocked or isolated third-party cookies by default. Chrome, with roughly two-thirds of the global browser share, still allowed them while promising to change. The entire advertising and analytics industry was building toward the date Chrome would join the other two. That date kept moving, and then it stopped moving for a reason nobody had planned for.

2020-2025: the phase-out that wasn’t

Google first said it would phase out third-party cookies in Chrome in January 2020, calling it a two-year project under the Privacy Sandbox umbrella. The Privacy Sandbox was the replacement plan: a set of APIs meant to deliver the things third-party cookies delivered, without the cross-site identifier. Topics would expose coarse interest categories computed on-device. Protected Audience (originally FLEDGE) would run remarketing auctions in the browser. Attribution Reporting would measure conversions without joining click and conversion identities. The pitch was that advertising could keep working on aggregate, on-device signals while the global per-user cookie went away.

The two-year timeline became a five-year saga. The deadline moved to 2022, then 2023, then 2024, then 2025. Two forces kept pushing it back. The advertising industry argued, with data, that the Sandbox APIs did not replace the revenue cookies generated. And the UK’s Competition and Markets Authority had taken jurisdiction over the whole plan, because a browser with Chrome’s share unilaterally removing a mechanism its own ad business could partly route around raised obvious competition concerns. Google had given the CMA formal commitments in 2022 that it would not deprecate cookies without the regulator’s sign-off. The fox had agreed to let an inspector watch the henhouse.

The data did not cooperate with the plan. In June 2025 the CMA published testing results showing that publisher revenue per impression ran roughly 30 percent lower without third-party cookies, even with the Privacy Sandbox available as a substitute. A 30 percent haircut on programmatic revenue is not a rounding error; it is the difference between a viable ad-funded publisher and a dead one. With that number on the table, the political and economic case for forcing the change through evaporated.

The five-year phase-out, and the reversal Jan 2020 announce phase-out Feb 2020 Chrome 80 Lax default Jul 2024 "user choice" prompt instead Apr 2025 no prompt; cookies stay Oct 2025 Sandbox APIs retired Jun 2025: CMA testing finds publisher revenue ~30% lower without third-party cookies, even with the Privacy Sandbox available as a substitute. Survivors: CHIPS (partitioned cookies) and FedCM. Retired: Topics, Protected Audience, Attribution Reporting, Private Aggregation, Shared Storage, and the rest of the ad APIs. *The arc that the ad-tech industry spent five years and untold engineering hours preparing for, ending where it started.*

The reversal came in two steps. In July 2024 Google abandoned the unilateral phase-out and proposed a “user choice” model instead: a one-time Chrome prompt letting each person decide whether to block third-party cookies. Then on 22 April 2025, Anthony Chavez, Google’s VP of Privacy Sandbox, announced that even the prompt was off. Google would “maintain our current approach to offering users third-party cookie choice in Chrome” and “not be rolling out a new standalone prompt for third-party cookies.” Third-party cookies stay on by default in Chrome. The controls live where they always lived, buried in privacy settings. After five years, the answer was to change nothing.

The Privacy Sandbox itself did not survive the climbdown. On 17 October 2025 Chavez announced that Google was retiring most of the advertising APIs, citing “their expected value and … their low levels of adoption.” Topics, Protected Audience, Attribution Reporting, Private Aggregation, Shared Storage, Protected App Signals, On-Device Personalization, and several more were all wound down for Chrome and Android. The CMA released Google from its 2022 commitments the same month, having concluded its competition concerns no longer applied once Google had given up on removing the thing it was worried about Google removing. Six years of replacement engineering, retired for lack of uptake.

Two pieces were explicitly kept alive, and they are the interesting ones. CHIPS and FedCM “have seen broad adoption, including support from other browsers,” and Google said it would keep supporting both. That is the tell about what the cookie debate was actually about.

What survives: partitioning and federated identity

CHIPS is Firefox’s Total Cookie Protection turned into an opt-in cookie attribute. Edited by Dylan Cutler and Aaron Selya in the Privacy Community Group, it adds a Partitioned keyword to Set-Cookie. A cookie set as partitioned gets stored under two keys instead of one: the usual host key, plus a partition key derived from the site of the top-level page the browser was on when the cookie was set. The canonical example from the spec:

Set-Cookie: __Host-SID=31d4d96e407aad42; SameSite=None; Secure; Path=/; Partitioned;

A Partitioned cookie must be Secure, and the __Host- prefix is recommended so the cookie binds to a single host with no Domain scope to leak across subdomains. The effect: an embedded map widget, a support-chat iframe, or a CDN that load-balances per top-level site can keep state inside one first-party context and never carry that state to another. The same third party on shoes.example and on news.example gets two unrelated cookie jars. The legitimate cross-site uses of cookies survive; the cross-site identifier does not. This is the post-third-party-cookie identity model in one attribute, and the CHIPS and partitioned cookies story is worth reading on its own because the partition-key edge cases are where the privacy guarantees actually live.

FedCM, the Federated Credential Management API, attacks the other thing third-party cookies were doing: keeping you logged in across the federated-login boundary. “Sign in with Google” historically leaned on third-party cookies and redirects and iframes, the exact mechanisms the privacy work was cutting off. FedCM replaces that plumbing with a browser-mediated identity flow, so federated login keeps working even in a browser that isolates or blocks third-party cookies. It is the identity layer being made explicit, lifted out of the cookie’s opaque value and into an API the browser actually understands.

That distinction is the whole point. The cookie was carrying two different jobs in the same opaque string: this is a session on this site, and this is the same person across all sites. Partitioning keeps the first and breaks the second by making the storage key include the top-level site. FedCM takes the cross-site-identity job that was legitimate (federated login you consented to) and gives it a real protocol, so it stops needing to ride a cross-site cookie. What gets killed is the third use, the one nobody consented to: the same id silently following you across the open web because an ad network’s pixel was embedded everywhere.

The striking thing about the 2020-2025 saga is how little the cookie itself changed and how much the politics around it did. The format Montulli sketched in 1994 is still the format. The session cookie that logs you into your bank is the same primitive as the tracking cookie that followed you to buy shoes, distinguished only by a SameSite keyword and, now, an optional Partitioned flag. The web’s identity layer was never replaced. It was annotated.

What actually shifted is where the cross-site identifier can live. Safari and Firefox closed the silent-cross-site-cookie door years ago and the ad industry adapted, mostly by moving identity server-side, into first-party data and email-hash graphs and fingerprinting that does not need a cookie at all. Chrome’s decision to keep third-party cookies on by default is less a reprieve for the cookie than an admission that the alternatives the industry already reached for are not obviously better for privacy, just harder for a browser to see. A blocked cookie is a visible thing with a name and an attribute. A device fingerprint assembled from TLS handshakes, header order, and canvas rendering is not, and it does not ask permission. If you run a crawler or proxy fleet you already know that the cookie was always the easy part of staying recognised; the hard signals were never in the Cookie header.

The honest summary as of late 2025: third-party cookies are dead in two of the three major browsers and alive by default in the third, the multi-year plan to kill them everywhere has been formally abandoned, the replacement APIs are mostly cancelled, and the one part of the replacement that shipped is partitioning, which Firefox had already built. The cookie won by attrition. It is still four bytes of opaque state the server hands you and asks you to hand back, and after thirty years and one of the most expensive standards fights in the history of the web, that is still the most that anyone can say about it with certainty.


Sources & further reading

Further reading