Safari’s Intelligent Tracking Prevention: What It Means for Your Web App
Safari’s Intelligent Tracking Prevention (ITP) caps third‑party cookie lifetimes and uses machine learning to block trackers. Learn how to spot the impact, avoid login breakage, and use the Storage Access API to keep your users happy.
24 Sept 2025, 11:15 UTC

The Problem: Safari’s ITP Becomes a Cookie Barrier
When a user visits example.com and that page loads a script from tracker.com, Safari’s Intelligent Tracking Prevention (ITP) kicks in. ITP examines the request, compares the domain against a curated list of known trackers, and then applies a machine‑learning heuristic to unknown domains. If the request is deemed a tracker, Safari blocks the third‑party cookie that the script would normally set. Even if the cookie is allowed, ITP enforces a hard 7‑day expiration on any client‑side cookie written via document.cookie. In practice, this means persistent login sessions that rely solely on a cookie can break after a week.
How ITP Works Under the Hood
- Curated List vs. Heuristics: Known trackers are identified by an Apple‑maintained list. Unknown domains are scored by a lightweight on‑device model that looks for patterns such as high request frequency, cross‑domain storage, or repeated cookie writes.
- Cookie Cap: Any cookie set via JavaScript that survives the ITP filter will have its maximum age reduced to 7 days. This cap is enforced regardless of the
max-ageattribute you specify. - Storage Access API: Safari exposes a standardized API that lets a third‑party script request explicit permission to read and write its own cookies in the context of a top‑level site. The user must grant this access, typically through a prompt or a consent banner.
Note that Safari on macOS applies these rules at the browser level, whereas iOS Safari enforces stricter OS‑level sandboxing that can block even first‑party storage in some contexts. Developers should test on both platforms.
Concrete Example: A Three‑Step Login Flow
Consider a site that uses a third‑party OAuth provider hosted at auth.example.com. The flow is:
- User visits
https://app.example.comand clicks “Login with Example”. - The page opens a popup to
https://auth.example.com, which sets a cookie named_authwithmax-age=2592000(30 days). - After successful authentication, the popup redirects back to the app, which reads the cookie to establish a session.
In Safari, the popup’s third‑party cookie is blocked by ITP because auth.example.com is not on the known‑tracker list. Even if the site were on the list, the 7‑day cap would truncate the cookie’s lifespan. The result is that the user is logged out after a week or never logged in at all.
To illustrate the cap, run the following in the browser console of auth.example.com (with the page loaded in Safari):
document.cookie = "_auth=abc123; max-age=2592000; path=/; secure; SameSite=None";
console.log(document.cookie);
Open the Storage tab in Safari’s Web Inspector, locate the _auth cookie, and confirm that its Expires date is only 7 days from the set time. If the expiration is longer, Safari is not applying the cap, which indicates the cookie is being set by a first‑party script.
Trade‑Offs and Workarounds
- First‑Party Cookies: Move authentication logic to the main domain. Store the session token in a first‑party cookie or in
localStorageand use refresh tokens on the server side. - Storage Access API: If you must use third‑party cookies, request access via
document.requestStorageAccess(). The user will see a prompt; if accepted, Safari lifts the third‑party restriction for that domain for the duration of the session. - Server‑Side Sessions: Store a short‑lived session identifier in a cookie and keep the heavy data on the server. This reduces reliance on client‑side cookie longevity.
- Feature Detection: Use
navigator.cookieEnabledand inspect the cookie’sexpiresattribute to detect if ITP has capped it. If the expiration is 7 days, trigger a fallback flow.
Below is a minimal fallback script that checks for the 7‑day cap and, if detected, initiates a server‑side token refresh:
function checkAuthCookie() {
const cookie = document.cookie.match(/_auth=([^;]+)/);
if (!cookie) return;
const expires = getCookieExpiry('_auth'); // custom helper
if (expires < Date.now() + 7 * 24 * 60 * 60 * 1000) {
// cookie will expire soon – refresh token
fetch('/refresh-token', { credentials: 'include' })
.then(r => r.json())
.then(data => document.cookie = `auth=${data.token}; max-age=2592000; path=/; secure; SameSite=None`);
}
}
// Run on page load
checkAuthCookie();
Limitations & Caveats
- Heuristic detection can flag legitimate first‑party scripts that exhibit tracker‑like patterns (e.g., high request frequency). Test thoroughly on Safari to avoid false positives.
- The 7‑day cap is hard‑coded; future Safari releases might alter the value or apply it to more cookie types.
- Storage Access API is only available in Safari 13+ and requires user interaction; it is not a silver bullet for all use cases.
Actionable Checklist for Safari‑Ready Apps
- Audit all third‑party scripts and identify those that set cookies.
- Move critical session logic to first‑party storage whenever possible.
- Implement a fallback that detects the 7‑day cap and refreshes tokens server‑side.
- Use the Storage Access API for essential third‑party cookies, and test the user prompt flow.
- Continuously monitor the Storage tab in Safari’s Web Inspector during development to catch any ITP‑related changes.
- Keep an eye on Apple’s WebKit documentation for updates to ITP behavior.
By anticipating Safari’s ITP constraints and building in graceful degradation, you can deliver a seamless authentication experience without compromising user privacy.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.