May 28, 2025
Reliably Detecting Third-Party Cookie Blocking In 2025

The web is beginning to part ways with third-party cookies, a technology it once heavily relied on. Introduced in 1994 by Netscape to support features like virtual shopping carts, cookies have long been a staple of web functionality. However, concerns over privacy and security have led to a concerted effort to eliminate them. The World Wide Web Consortium Technical Architecture Group (W3C TAG) has been vocal in advocating for the complete removal of third-party cookies from the web platform.

Major browsers (Chrome, Safari, Firefox, and Edge) are responding by phasing them out, though the transition is gradual. While this shift enhances user privacy, it also disrupts legitimate functionalities that rely on third-party cookies, such as single sign-on (SSO), fraud prevention, and embedded services. And because there is still no universal ban in place and many essential web features continue to depend on these cookies, developers must detect when third-party cookies are blocked so that applications can respond gracefully.

Don’t Let Silent Failures Win: Why Cookie Detection Still Matters

Yes, the ideal solution is to move away from third-party cookies altogether and redesign our integrations using privacy-first, purpose-built alternatives as soon as possible. But in reality, that migration can take months or even years, especially for legacy systems or third-party vendors. Meanwhile, users are already browsing with third-party cookies disabled and often have no idea that anything is missing.

Imagine a travel booking platform that embeds an iframe from a third-party partner to display live train or flight schedules. This embedded service uses a cookie on its own domain to authenticate the user and personalize content, like showing saved trips or loyalty rewards. But when the browser blocks third-party cookies, the iframe cannot access that data. Instead of a seamless experience, the user sees an error, a blank screen, or a login prompt that doesn’t work.

And while your team is still planning a long-term integration overhaul, this is already happening to real users. They don’t see a cookie policy; they just see a broken booking flow.

Detecting third-party cookie blocking isn’t just good technical hygiene but a frontline defense for user experience.

Why It’s Hard To Tell If Third-Party Cookies Are Blocked

Detecting whether third-party cookies are supported isn’t as simple as calling navigator.cookieEnabled. Even a well-intentioned check like this one may look safe, but it still won’t tell you what you actually need to know:

// DOES NOT detect third-party cookie blocking
function areCookiesEnabled() {
if (navigator.cookieEnabled === false) {
return false;
}

try {
document.cookie = “test_cookie=1; SameSite=None; Secure”;
const hasCookie = document.cookie.includes(“test_cookie=1”);
document.cookie = “test_cookie=; Max-Age=0; SameSite=None; Secure”;

return hasCookie;
} catch (e) {
return false;
}
}

This function only confirms that cookies work in the current (first-party) context. It says nothing about third-party scenarios, like an iframe on another domain. Worse, it’s misleading: in some browsers, navigator.cookieEnabled may still return true inside a third-party iframe even when cookies are blocked. Others might behave differently, leading to inconsistent and unreliable detection.

These cross-browser inconsistencies — combined with the limitations of document.cookie — make it clear that there is no shortcut for detection. To truly detect third-party cookie blocking, we need to understand how different browsers actually behave in embedded third-party contexts.

How Modern Browsers Handle Third-Party Cookies

The behavior of modern browsers directly affects which detection methods will work and which ones silently fail.

Safari: Full Third-Party Cookie Blocking

Since version 13.1, Safari blocks all third-party cookies by default, with no exceptions, even if the user previously interacted with the embedded domain. This policy is part of Intelligent Tracking Prevention (ITP).

For embedded content (such as an SSO iframe) that requires cookie access, Safari exposes the Storage Access API, which requires a user gesture to grant storage permission. As a result, a test for third-party cookie support will nearly always fail in Safari unless the iframe explicitly requests access via this API.

Firefox: Cookie Partitioning By Design

Firefox’s Total Cookie Protection isolates cookies on a per-site basis. Third-party cookies can still be set and read, but they are partitioned by the top-level site, meaning a cookie set by the same third-party on siteA.com and siteB.com is stored separately and cannot be shared.

As of Firefox 102, this behavior is enabled by default in the Standard (default) mode of Enhanced Tracking Protection. Unlike the Strict mode — which blocks third-party cookies entirely, similar to Safari — the Standard mode does not block them outright. Instead, it neutralizes their tracking capability by isolating them per site.

As a result, even if a test shows that a third-party cookie was successfully set, it may be useless for cross-site logins or shared sessions due to this partitioning. Detection logic needs to account for that.

Chrome: From Deprecation Plans To Privacy Sandbox (And Industry Pushback)

Chromium-based browsers still allow third-party cookies by default — but the story is changing. Starting with Chrome 80, third-party cookies must be explicitly marked with SameSite=None; Secure, or they will be rejected.

In January 2020, Google announced their intention to phase out third-party cookies by 2022. However, the timeline was updated multiple times, first in June 2021 when the company pushed the rollout to begin in mid-2023 and conclude by the end of that year. Additional postponements followed in July 2022, December 2023, and April 2024.

In July 2024, Google has clarified that there is no plan to unilaterally deprecate third-party cookies or force users into a new model without consent. Instead, Chrome is shifting to a user-choice interface that will allow individuals to decide whether to block or allow third-party cookies globally.

This change was influenced in part by substantial pushback from the advertising industry, as well as ongoing regulatory oversight, including scrutiny by the UK Competition and Markets Authority (CMA) into Google’s Privacy Sandbox initiative. The CMA confirmed in a 2025 update that there is no intention to force a deprecation or trigger automatic prompts for cookie blocking.

As for now, third-party cookies remain enabled by default in Chrome. The new user-facing controls and the broader Privacy Sandbox ecosystem are still in various stages of experimentation and limited rollout.

Edge (Chromium-Based): Tracker-Focused Blocking With User Configurability

Edge (which is a Chromium-based browser) shares Chrome’s handling of third-party cookies, including the SameSite=None; Secure requirement. Additionally, Edge introduces Tracking Prevention modes: Basic, Balanced (default), and Strict. In Balanced mode, it blocks known third-party trackers using Microsoft’s maintained list but allows many third-party cookies that are not classified as trackers. Strict mode blocks more resource loads than Balanced, which may result in some websites not behaving as expected.

Other Browsers: What About Them?

Privacy-focused browsers, like Brave, block third-party cookies by default as part of their strong anti-tracking stance.

Internet Explorer (IE) 11 allowed third-party cookies depending on user privacy settings and the presence of Platform for Privacy Preferences (P3P) headers. However, IE usage is now negligible. Notably, the default “Medium” privacy setting in IE could block third-party cookies unless a valid P3P policy was present.

Older versions of Safari had partial third-party cookie restrictions (such as “Allow from websites I visit”), but, as mentioned before, this was replaced with full blocking via ITP.

As of 2025, all major browsers either block or isolate third-party cookies by default, with the exception of Chrome, which still allows them in standard browsing mode pending the rollout of its new user-choice model.

To account for these variations, your detection strategy must be grounded in real-world testing — specifically by reproducing a genuine third-party context such as loading your script within an iframe on a cross-origin domain — rather than relying on browser names or versions.

Overview Of Detection Techniques

Over the years, many techniques have been used to detect third-party cookie blocking. Most are unreliable or obsolete. Here’s a quick walkthrough of what doesn’t work (and why) and what does.

Basic JavaScript API Checks (Misleading)

As mentioned earlier, the navigator.cookieEnabled or setting document.cookie on the main page doesn’t reflect cross-site cookie status:

In third-party iframes, navigator.cookieEnabled often returns true even when cookies are blocked.
Setting document.cookie in the parent doesn’t test the third-party context.

These checks are first-party only. Avoid using them for detection.

Storage Hacks Via localStorage (Obsolete)

Previously, some developers inferred cookie support by checking if window.localStorage worked inside a third-party iframe — which is especially useful against older Safari versions that blocked all third-party storage.

Modern browsers often allow localStorage even when cookies are blocked. This leads to false positives and is no longer reliable.

Server-Assisted Cookie Probe (Heavyweight)

One classic method involves setting a cookie from a third-party domain via HTTP and then checking if it comes back:

Load a script/image from a third-party server that sets a cookie.
Immediately load another resource, and the server checks whether the cookie was sent.

This works, but it:

Requires custom server-side logic,
Depends on HTTP caching, response headers, and cookie attributes (SameSite=None; Secure), and
Adds development and infrastructure complexity.

While this is technically valid, it is not suitable for a front-end-only approach, which is our focus here.

Storage Access API (Supplemental Signal)

The document.hasStorageAccess() method allows embedded third-party content to check if it has access to unpartitioned cookies:

Chrome
Supports hasStorageAccess() and requestStorageAccess() starting from version 119. Additionally, hasUnpartitionedCookieAccess() is available as an alias for hasStorageAccess() from version 125 onwards.
Firefox
Supports both hasStorageAccess() and requestStorageAccess() methods.
Safari
Supports the Storage Access API. However, access must always be triggered by a user interaction. For example, even calling requestStorageAccess() without a direct user gesture (like a click) is ignored.

Chrome and Firefox also support the API, and in those browsers, it may work automatically or based on browser heuristics or site engagement.

This API is particularly useful for detecting scenarios where cookies are present but partitioned (e.g., Firefox’s Total Cookie Protection), as it helps determine if the iframe has unrestricted cookie access. But for now, it’s still best used as a supplemental signal, rather than a standalone check.

iFrame + postMessage (Best Practice)

Despite the existence of the Storage Access API, at the time of writing, this remains the most reliable and browser-compatible method:

Embed a hidden iframe from a third-party domain.
Inside the iframe, attempt to set a test cookie.
Use window.postMessage to report success or failure to the parent.

This approach works across all major browsers (when properly configured), requires no server (kind of, more on that next), and simulates a real-world third-party scenario.

We’ll implement this step-by-step next.

Bonus: Sec-Fetch-Storage-Access

Chrome (starting in version 133) is introducing Sec-Fetch-Storage-Access, an HTTP request header sent with cross-site requests to indicate whether the iframe has access to unpartitioned cookies. This header is only visible to servers and cannot be accessed via JavaScript. It’s useful for back-end analytics but not applicable for client-side cookie detection.

As of May 2025, this feature is only implemented in Chrome and is not supported by other browsers. However, it’s still good to know that it’s part of the evolving ecosystem.

Step-by-Step: Detecting Third-Party Cookies Via iFrame

So, what did I mean when I said that the last method we looked at “requires no server”? While this method doesn’t require any back-end logic (like server-set cookies or response inspection), it does require access to a separate domain — or at least a cross-site subdomain — to simulate a third-party environment. This means the following:

You must serve the test page from a different domain or public subdomain, e.g., example.com and cookietest.example.com,
The domain needs HTTPS (for SameSite=None; Secure cookies to work), and
You’ll need to host a simple static file (the test page), even if no server code is involved.

Once that’s set up, the rest of the logic is fully client-side.

Step 1: Create A Cookie Test Page (On A Third-Party Domain)

Minimal version (e.g., https://cookietest.example.com/cookie-check.html):

<!DOCTYPE html>
<html>
<body>
<script>
document.cookie = “thirdparty_test=1; SameSite=None; Secure; Path=/;”;
const cookieFound = document.cookie.includes(“thirdparty_test=1”);

const sendResult = (status) => window.parent?.postMessage(status, “*”);

if (cookieFound && document.hasStorageAccess instanceof Function) {
document.hasStorageAccess().then((hasAccess) => {
sendResult(hasAccess ? “TP_COOKIE_SUPPORTED” : “TP_COOKIE_BLOCKED”);
}).catch(() => sendResult(“TP_COOKIE_BLOCKED”));
} else {
sendResult(cookieFound ? “TP_COOKIE_SUPPORTED” : “TP_COOKIE_BLOCKED”);
}
</script>
</body>
</html>

Make sure the page is served over HTTPS, and the cookie uses SameSite=None; Secure. Without these attributes, modern browsers will silently reject it.

Step 2: Embed The iFrame And Listen For The Result

On your main page:

function checkThirdPartyCookies() {
return new Promise((resolve) => {
const iframe = document.createElement(‘iframe’);
iframe.style.display = ‘none’;
iframe.src = “https://cookietest.example.com/cookie-check.html”; // your subdomain
document.body.appendChild(iframe);

let resolved = false;
const cleanup = (result, timedOut = false) => {
if (resolved) return;
resolved = true;
window.removeEventListener(‘message’, onMessage);
iframe.remove();
resolve({ thirdPartyCookiesEnabled: result, timedOut });
};

const onMessage = (event) => {
if ([“TP_COOKIE_SUPPORTED”, “TP_COOKIE_BLOCKED”].includes(event.data)) {
cleanup(event.data === “TP_COOKIE_SUPPORTED”, false);
}
};

window.addEventListener(‘message’, onMessage);
setTimeout(() => cleanup(false, true), 1000);
});
}

Example usage:

checkThirdPartyCookies().then(({ thirdPartyCookiesEnabled, timedOut }) => {
if (!thirdPartyCookiesEnabled) {
someCookiesBlockedCallback(); // Third-party cookies are blocked.
if (timedOut) {
// No response received (iframe possibly blocked).
// Optional fallback UX goes here.
someCookiesBlockedTimeoutCallback();
};
}
});

Step 3: Enhance Detection With The Storage Access API

In Safari, even when third-party cookies are blocked, users can manually grant access through the Storage Access API — but only in response to a user gesture.

Here’s how you could implement that in your iframe test page:

<button id=”enable-cookies”>This embedded content requires cookie access. Click below to continue.</button>

<script>
document.getElementById(‘enable-cookies’)?.addEventListener(‘click’, async () => {
if (document.requestStorageAccess && typeof document.requestStorageAccess === ‘function’) {
try {
const granted = await document.requestStorageAccess();
if (granted !== false) {
window.parent.postMessage(“TP_STORAGE_ACCESS_GRANTED”, “*”);
} else {
window.parent.postMessage(“TP_STORAGE_ACCESS_DENIED”, “*”);
}
} catch (e) {
window.parent.postMessage(“TP_STORAGE_ACCESS_FAILED”, “*”);
}
}
});
</script>

Then, on the parent page, you can listen for this message and retry detection if needed:

// Inside the same onMessage listener from before:
if (event.data === “TP_STORAGE_ACCESS_GRANTED”) {
// Optionally: retry the cookie test, or reload iframe logic
checkThirdPartyCookies().then(handleResultAgain);
}

(Bonus) A Purely Client-Side Fallback (Not Perfect, But Sometimes Necessary)

In some situations, you might not have access to a second domain or can’t host third-party content under your control. That makes the iframe method unfeasible.

When that’s the case, your best option is to combine multiple signals — basic cookie checks, hasStorageAccess(), localStorage fallbacks, and maybe even passive indicators like load failures or timeouts — to infer whether third-party cookies are likely blocked.

The important caveat: This will never be 100% accurate. But, in constrained environments, “better something than nothing” may still improve the UX.

Here’s a basic example:

async function inferCookieSupportFallback() {
let hasCookieAPI = navigator.cookieEnabled;
let canSetCookie = false;
let hasStorageAccess = false;

try {
document.cookie = “testfallback=1; SameSite=None; Secure; Path=/;”;
canSetCookie = document.cookie.includes(“test_fallback=1”);

document.cookie = “test_fallback=; Max-Age=0; Path=/;”;
} catch (_) {
canSetCookie = false;
}

if (typeof document.hasStorageAccess === “function”) {
try {
hasStorageAccess = await document.hasStorageAccess();
} catch (_) {}
}

return {
inferredThirdPartyCookies: hasCookieAPI && canSetCookie && hasStorageAccess,
raw: { hasCookieAPI, canSetCookie, hasStorageAccess }
};
}

Example usage:

inferCookieSupportFallback().then(({ inferredThirdPartyCookies }) => {
if (inferredThirdPartyCookies) {
console.log(“Cookies likely supported. Likely, yes.”);
} else {
console.warn(“Cookies may be blocked or partitioned.”);
// You could inform the user or adjust behavior accordingly
}
});

Use this fallback when:

You’re building a JavaScript-only widget embedded on unknown sites,
You don’t control a second domain (or the team refuses to add one), or
You just need some visibility into user-side behavior (e.g., debugging UX issues).

Don’t rely on it for security-critical logic (e.g., auth gating)! But it may help tailor the user experience, surface warnings, or decide whether to attempt a fallback SSO flow. Again, it’s better to have something rather than nothing.

Fallback Strategies When Third-Party Cookies Are Blocked

Detecting blocked cookies is only half the battle. Once you know they’re unavailable, what can you do? Here are some practical options that might be useful for you:

Redirect-Based Flows

For auth-related flows, switch from embedded iframes to top-level redirects. Let the user authenticate directly on the identity provider’s site, then redirect back. It works in all browsers, but the UX might be less seamless.

Request Storage Access

Prompt the user using requestStorageAccess() after a clear UI gesture (Safari requires this). Use this to re-enable cookies without leaving the page.

Token-Based Communication

Pass session info directly from parent to iframe via:

postMessage (with required origin);
Query params (e.g., signed JWT in iframe URL).

This avoids reliance on cookies entirely but requires coordination between both sides:

// Parent
const iframe = document.getElementById(‘my-iframe’);

iframe.onload = () => {
const token = getAccessTokenSomehow(); // JWT or anything else
iframe.contentWindow.postMessage(
{ type: ‘AUTH_TOKEN’, token },
https://iframe.example.com’ // Set the correct origin!
);
};

// iframe
window.addEventListener(‘message’, (event) => {
if (event.origin !== ‘https://parent.example.com’) return;

const { type, token } = event.data;

if (type === ‘AUTH_TOKEN’) {
validateAndUseToken(token); // process JWT, init session, etc
}
});

Partitioned Cookies (CHIPS)

Chrome (since version 114) and other Chromium-based browsers now support cookies with the Partitioned attribute (known as CHIPS), allowing per-top-site cookie isolation. This is useful for widgets like chat or embedded forms where cross-site identity isn’t needed.

Note: Firefox and Safari don’t support the Partitioned cookie attribute. Firefox enforces cookie partitioning by default using a different mechanism (Total Cookie Protection), while Safari blocks third-party cookies entirely.

But be careful, as they are treated as “blocked” by basic detection. Refine your logic if needed.

Final Thought: Transparency, Transition, And The Path Forward

Third-party cookies are disappearing, albeit gradually and unevenly. Until the transition is complete, your job as a developer is to bridge the gap between technical limitations and real-world user experience. That means:

Keep an eye on the standards.
APIs like FedCM and Privacy Sandbox features (Topics, Attribution Reporting, Fenced Frames) are reshaping how we handle identity and analytics without relying on cross-site cookies.
Combine detection with graceful fallback.
Whether it’s offering a redirect flow, using requestStorageAccess(), or falling back to token-based messaging — every small UX improvement adds up.
Inform your users.
Users shouldn’t be left wondering why something worked in one browser but silently broke in another. Don’t let them feel like they did something wrong — just help them move forward. A clear, friendly message can prevent this confusion.

The good news? You don’t need a perfect solution today, just a resilient one. By detecting issues early and handling them thoughtfully, you protect both your users and your future architecture, one cookie-less browser at a time.

And as seen with Chrome’s pivot away from automatic deprecation, the transition is not always linear. Industry feedback, regulatory oversight, and evolving technical realities continue to shape the time and the solutions.

And don’t forget: having something is better than nothing.

Leave a Reply

Your email address will not be published. Required fields are marked *

Send