↑↓ to move ↵ to open Esc to close Browse all tools

Security guide

First-Party vs Third-Party Cookies: What Each One Does

A cookie is a small piece of data a site asks the browser to keep and send back. Whether it counts as first-party or third-party depends only on where you are when it is sent. Here is what decides it, the attributes that control every cookie, what Firefox, Safari and Chrome do with third-party cookies today, and what a site that relies on them can use instead.

What a cookie is

A server sets a cookie with a Set-Cookie header in its response. The browser stores the name and value and sends it back in a Cookie header on later requests to the same place. That is how a site remembers that you logged in, what is in your cart, or which language you picked. Each cookie comes with attributes that say where it may be sent, for how long, and under which conditions:

Set-Cookie: session=7yjgj57e; Secure; HttpOnly; SameSite=Lax; Max-Age=86400

The HTTP header checker shows the Set-Cookie headers a page sends, with every attribute.

First-party or third-party

MDN puts the rule in one sentence: if the cookie's domain and scheme match the page in the address bar, it is a first-party cookie. If they do not, it is a third-party cookie. So it is not the cookie that is first- or third-party, it is the situation.

MDN's example is a sign-in widget hosted at auth.site and embedded on three other sites. When you sign in on one of them, auth.site sets a session cookie. On the other two sites, the embedded widget sends that cookie back to auth.site and you are signed in at once. On auth.site itself, that cookie is first-party. Inside the widget on someone else's site, it is third-party. The same mechanism lets an ad or analytics script embedded on many sites recognize one browser across all of them, which is why browsers restrict it.

The attributes every cookie has

AttributeWhat it does
Domain=example.comSent to example.com and all its subdomains. Left out, the cookie is host-only.
Expires=date / Max-Age=NWhen it expires. Neither set: a session cookie, removed when the browser session ends. Max-Age wins if both are set.
SecureSent only over https (localhost excepted).
HttpOnlyHidden from JavaScript (document.cookie), still sent with requests.
SameSite=Strict / Lax / NoneWhether it goes along with cross-site requests. None requires Secure.
PartitionedStored in a separate jar per top-level site (CHIPS). Requires Secure.

A few rules from MDN catch people out. A response from api.example.com may set Domain=example.com but not Domain=other.example.com, and never a public suffix like com or co.uk. Cookies that break this are ignored. A leading dot, as in .example.com, is ignored too. And names with special prefixes add rules: a cookie named __Host- something must be Secure, have Path=/ and no Domain, which pins it to the exact host that set it. That makes it a good choice for session cookies.

HttpOnly deserves a note. It hides the cookie from document.cookie, but MDN points out that the cookie is still sent with requests made by JavaScript through fetch(). It protects the value from being read by an injected script, not from being used.

SameSite: the cross-site switch

SameSite controls whether a cookie travels with requests that start on another site. MDN says it gives some protection against cross-site request forgery, and it is also what decides whether a cookie can work as a third-party cookie at all:

ValueWhen the cookie is sent
StrictOnly for requests from the same site that set it
LaxSame site, plus top-level navigations to the site with a safe method such as GET (clicking a link)
NoneSame-site and cross-site requests, including embeds; needs Secure

With Lax, a cookie goes along when you click a link to the site, but not with a fetch() call, an image or a form POST from another site. MDN notes that some browsers apply Lax when no SameSite value is given. A cookie meant to work inside an embed on other sites therefore has to say SameSite=None; Secure explicitly.

What browsers do with third-party cookies

This is the part that has changed most over the years, so here is only what the official pages said when this guide was written:

BrowserDefault for third-party cookies
FirefoxTotal Cookie Protection, on by default with Enhanced Tracking Protection: a separate cookie jar per site
SafariCross-site cookies blocked by default since WebKit's March 2020 update
ChromeNot blocked by default; blocked in Incognito or when the user turns blocking on

Safari's change came in a WebKit post dated March 24, 2020, which said cookies for cross-site resources are now blocked by default across the board. Firefox's Total Cookie Protection does not delete third-party cookies, it splits them: a tracker embedded on two sites gets two separate jars and cannot connect them. For Chrome, MDN says third-party cookies are not blocked by default, only in Incognito mode or when the user turns blocking on in settings. Google's Privacy Sandbox blog, in a post dated October 17, 2025, said Chrome will maintain its current approach to offering users third-party cookie choice. Check these pages again before relying on any of it.

If your site depends on third-party cookies

  • Use first-party cookies where you can. A login on your own domain, set with Secure, HttpOnly and SameSite=Lax, is unaffected by any of the blocking above.
  • Partitioned cookies (CHIPS). Add the Partitioned attribute and the embed gets its own cookie jar per top-level site. It keeps working inside each site but cannot follow the user from one to the next. MDN describes this as only requiring the attribute on existing cross-site cookies.
  • Storage Access API. For a small number of related sites, an embed can ask the user, per frame, for access to its unpartitioned cookies.
  • Tokens instead of cookies. An API called from your own page can take a token in an Authorization header. The JWT vs session cookies guide compares the two, and the JWT decoder shows what a token contains.

Size and number

RFC 6265 asks browsers to support at least 4,096 bytes per cookie, at least 50 cookies per domain and at least 3,000 cookies in total. Every cookie for a site goes out with every matching request, so 20 cookies of 200 bytes each add about 4 KB to each request, images and scripts included. Keep cookies few and small, store an ID, and keep the data on the server.

Checklist for a site's own cookies

  1. Session cookie: __Host- prefix, Secure, HttpOnly, SameSite=Lax or Strict, Path=/.
  2. Leave out Domain unless subdomains really need the cookie. The subdomain vs subdirectory guide shows when they do.
  3. Give every non-session cookie an explicit Max-Age.
  4. Use SameSite=None only for cookies that must work in embeds on other sites, and always with Secure.
  5. Calls from a page to an API on another origin also need CORS; the CORS guide explains why * fails with cookies.

Frequently asked questions

What is the difference between first-party and third-party cookies?

It depends on where you are, not on the cookie itself. MDN calls a cookie first-party when its domain and scheme match the page in the address bar, and third-party when they do not. The same cookie from a sign-in service is first-party when you visit that service and third-party when its widget is embedded in another site.

Are third-party cookies blocked?

In Firefox and Safari, by default. MDN says Firefox gives third-party cookies a separate jar per site through Total Cookie Protection, and WebKit announced in March 2020 that Safari blocks cookies for cross-site resources by default. Chrome does not block them by default; in October 2025 Google said Chrome will keep its current approach of offering users a choice.

Are first-party cookies safe?

They are not a tracking risk across sites, but a first-party session cookie is the key to your account. That is why it should be set with Secure, so it only travels over HTTPS, HttpOnly, so scripts cannot read it, and a SameSite value of Lax or Strict, which limits cross-site request forgery.

Why do my cookies not work inside an iframe?

A cookie set by a site embedded in an iframe on another site is a third-party cookie there. It needs SameSite=None and Secure to be sent at all, and Firefox and Safari still keep it in a jar tied to the top-level site or block it. Options are the Partitioned attribute, if the embed only needs its own state per site, or the Storage Access API, which asks the user for permission.

How big can a cookie be?

RFC 6265 says browsers should support at least 4,096 bytes per cookie, at least 50 cookies per domain and at least 3,000 cookies in total. Those are minimums, but they are also the safe limit to design for. Large data belongs on the server, with only an ID in the cookie.

Sources