Solving the 7‑Day Logout: Navigating Safari’s ITP Cookie Caps
Safari’s Intelligent Tracking Prevention caps JavaScript‑set cookies to 7 days, causing users to log out unexpectedly. Learn how to use server‑side Set‑Cookie headers to maintain longer sessions.
10 Sept 2026, 23:03 UTC

The Mystery of the Disappearing Session
When you set a session token to live for 30 days, you expect users to stay logged in for that period. In Safari on macOS and iOS, however, many users are forced to re‑authenticate exactly seven days after first login. The culprit is not a bug in your code but Safari’s Intelligent Tracking Prevention (ITP) engine, which caps client‑side cookies to a 7‑day maximum.
Client‑Side vs. Server‑Side Persistence
ITP distinguishes how a cookie is created. Cookies set via document.cookie are treated as potential third‑party trackers and are subject to the 7‑day cap. Cookies delivered through HTTP Set‑Cookie headers are generally exempt, as the server is directly establishing the session with the browser.
JavaScript‑Set Cookies (document.cookie)
Any cookie created by JavaScript, even with expires or max‑age set to a year, will be truncated to 7 days by Safari. The browser silently overrides your requested expiry.
HTTP Response Headers (Set‑Cookie)
When the server sends a Set‑Cookie header, Safari considers it a legitimate first‑party session token and does not apply the 7‑day cap. The cookie can persist for the full Max‑Age value you specify.
Concrete Example: Moving the Token to the Server
Below is a Node.js/Express snippet that sends a 30‑day session cookie via Set‑Cookie. Run this on the server side, not in browser JavaScript.
// Server‑side login handler (Node.js/Express)
// Requires server‑level access to response headers
app.post('/login', (req, res) => {
const token = generateAuthToken(req.body.user);
res.cookie('session_id', token, {
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days in ms
httpOnly: true, // prevents JS access
secure: true, // requires HTTPS
sameSite: 'Lax'
});
res.status(200).send('Logged in');
});
Because the cookie is set via HTTP headers, Safari will honor the 30‑day maxAge. The browser will automatically send the cookie with every request to the same domain.
LocalStorage and IndexedDB: The Hidden Pitfalls
ITP also monitors other client‑side storage APIs. If a domain is flagged as a tracker, Safari may purge localStorage or IndexedDB data after seven days of inactivity. Relying on these APIs for critical session data can therefore lead to unexpected logouts.
Verifying ITP Behavior
- Open Safari Web Inspector (⌥⌘I), go to the Storage tab.
- Locate your cookie in the Cookies section and note the Expires date.
- If the date is exactly seven days from creation, ITP is enforcing the cap.
To confirm that a server‑side Set‑Cookie persists beyond seven days, repeat the inspection after one week. The Expires date should reflect the full maxAge you set.
Trade‑Offs and Limitations
- Server‑side cookies improve persistence but require secure handling on the backend.
- Client‑side tokens are convenient for single‑page applications but will be truncated by Safari.
- Behavior may differ slightly between Safari on macOS and iOS due to platform‑specific WebKit layers.
- Third‑party cookies are blocked by default; no header manipulation can override that.
Actionable Takeaway
Audit your authentication flow. If you see document.cookie being used to store session tokens, move the logic to a server‑side Set‑Cookie header. This shift eliminates the 7‑day ITP cap and ensures a consistent user experience across browsers.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.