Partitioned Cookies (CHIPS)
Implement cross-site cookie partitioning to prevent tracking while preserving legitimate functionality
Understanding Partitioned Cookies and the CHIPS Specification
You've probably used an embedded chat widget on a website, or maybe a payment processor seamlessly integrated into an e-commerce checkout. These helpful tools work smoothly in the background, remembering your preferences and keeping you logged in. But have you ever wondered how they maintain state while embedded in someone else's website? The answer has traditionally been third-party cookiesβand they're at the center of one of the web's biggest privacy debates. In this section, we'll explore how partitioned cookies and the CHIPS specification (Cookies Having Independent Partitioned State) offer a privacy-preserving solution to this complex problem. Master these concepts with our free flashcards embedded throughout this lesson to solidify your understanding.
The Privacy Problem: When Cookies Become Surveillance Tools
Traditional third-party cookies have powered both legitimate functionality and invasive tracking for decades. Here's the problem: when a cookie is set by a domain different from the one in your browser's address bar, that cookie can be accessed across every site that embeds content from that third-party domain.
π― Key Principle: A traditional third-party cookie creates a single, shared identity that follows users across the entire web, enabling cross-site tracking at massive scale.
Imagine tracker.example sets a cookie with a unique identifier when you visit site-a.com. When you later visit site-b.com, site-c.com, and dozens of other sites that also embed resources from tracker.example, that same cookieβwith your unique IDβis sent along with each request. The tracker can now build a comprehensive profile of your browsing habits across unrelated websites.
User visits site-a.com (embeds tracker.example)
ββ> tracker.example sets cookie: user_id=12345
User visits site-b.com (embeds tracker.example)
ββ> tracker.example receives cookie: user_id=12345
ββ> Tracker now knows user 12345 visited both sites
User visits site-c.com (embeds tracker.example)
ββ> tracker.example receives cookie: user_id=12345
ββ> Profile grows richer with each site visit
This cross-site tracking capability has led browsers to take aggressive action, with Safari and Firefox blocking third-party cookies by default, and Chrome planning to follow suit. But here's the dilemma: not all third-party cookies are used for tracking. Many legitimate services genuinely need to maintain state when embedded in other sites.
π‘ Real-World Example: A SaaS customer support chat widget embedded on hundreds of client websites needs to remember your conversation history and login state. Without some form of third-party cookies, you'd be logged out every time you switched between different client sites using the same chat service.
Cookie Partitioning: Independent Cookie Jars for Each Context
Cookie partitioning fundamentally changes how third-party cookies work by creating separate "cookie jars" based on the top-level site where the cookie is set. Instead of one global cookie that works everywhere, each embedded context gets its own isolated storage.
π§ Mental Model: Think of traditional third-party cookies as a single passport that identifies you everywhere you travel. Partitioned cookies are like separate membership cardsβyour gym membership only works at the gym, your library card only at the library. Each is useful in its context but can't be combined to track your movements.
The CHIPS specification implements this partitioning using a partition key that combines:
- The top-level site (the domain in the browser's address bar)
- The cookie's domain attribute
When a cookie is set with the Partitioned attribute, it can only be accessed when both the top-level site AND the third-party domain match the original context where it was set.
User visits site-a.com
ββ> Embedded chat.example sets partitioned cookie: session=abc
ββ> Partition key: (site-a.com, chat.example)
User visits site-b.com
ββ> Embedded chat.example sets partitioned cookie: session=xyz
ββ> Partition key: (site-b.com, chat.example)
ββ> Different partition = different cookie!
User returns to site-a.com
ββ> chat.example receives only: session=abc
ββ> Cannot see session=xyz from site-b.com context
π€ Did you know? The partition key uses the site (scheme + eTLD+1) rather than the full origin, so https://shop.example.com and https://blog.example.com share the same partition key of https://example.com.
The Partitioned Attribute: Syntax and Semantics
The Partitioned attribute is a new cookie flag that explicitly opts a cookie into partitioned storage. Here's what it looks like:
Set-Cookie: session_id=abc123; Secure; Path=/; SameSite=None; Partitioned
π Quick Reference Card: Partitioned vs SameSite
| Attribute π·οΈ | Purpose π― | Scope π | Privacy Goal π |
|---|---|---|---|
SameSite=Strict |
Blocks cookie on cross-site requests | Same-site only | Prevent CSRF attacks |
SameSite=Lax |
Allows cookie on top-level navigations | Same-site + some cross-site | Balance security & UX |
SameSite=None |
Allows cookie on all cross-site requests | Global | Enable third-party functionality |
Partitioned |
Isolates cookie per top-level site | Per top-level context | Prevent cross-site tracking |
β οΈ Common Mistake: Confusing Partitioned with SameSite=Lax or SameSite=Strict.
Mistake 1: Assuming SameSite protects against tracking β οΈ
β Wrong thinking: "I set SameSite=Lax, so my cookies can't be used for tracking."
β
Correct thinking: "SameSite prevents CSRF but doesn't partition storage. Traditional third-party cookies with SameSite=None can still track across sites. Partitioned explicitly creates isolated storage per top-level site."
π‘ Remember: The Partitioned attribute requires Secure and must be used with SameSite=None because by definition, partitioned cookies are accessed in cross-site contexts.
Legitimate Use Cases: When Third-Party State Matters
While blocking all third-party cookies protects privacy, it breaks important functionality. Partitioned cookies preserve these use cases while preventing cross-site tracking:
π§ Embedded Services That Benefit from CHIPS:
Customer Support Widgets - Chat services embedded across multiple client sites need to maintain conversation state and authentication without being able to track users across unrelated websites.
Payment Processors - Payment widgets embedded in checkout flows need to remember fraud detection signals and user preferences within each merchant's context, but shouldn't be able to build shopping profiles across merchants.
SaaS Analytics Dashboards - Analytics services embedded in multiple customer dashboards need session management per customer without cross-customer tracking capability.
Embedded Content Platforms - Video players, document viewers, or interactive widgets that need to remember playback position or user preferences within each embedding site.
Headless CMS Previews - Content management systems that provide live preview embeds for editors need to maintain authentication state without global tracking.
π‘ Pro Tip: If your service is embedded in multiple unrelated sites and needs to maintain state, but doesn't need to correlate user behavior across those different top-level sites, partitioned cookies are the perfect fit.
Browser Support and the Third-Party Cookie Transition
The CHIPS specification emerged as part of the broader Privacy Sandbox initiative to provide privacy-preserving alternatives before third-party cookies are deprecated entirely.
Current Browser Support Status:
- π Chrome/Edge: Full support since Chrome 114 (May 2023)
- π Safari: Not yet implemented (uses full third-party cookie blocking instead)
- π Firefox: Under consideration (currently uses Total Cookie Protection with different partitioning approach)
π― Key Principle: CHIPS provides a migration path for legitimate third-party cookie use cases before complete third-party cookie deprecation. Services that adopt partitioned cookies now will continue functioning when traditional third-party cookies are blocked.
The relationship between CHIPS and third-party cookie deprecation:
Traditional Third-Party Cookies
|
v
[Privacy Concerns Identified]
|
+-----------+-----------+
| |
v v
Full Blocking Partitioned Cookies
(Safari/Firefox) (Chrome's CHIPS)
| |
v v
Breaks legitimate Preserves functionality
use cases Prevents tracking
π€ Did you know? Firefox's "Total Cookie Protection" actually implements a form of cookie partitioning by default for all third-party cookies, but uses a different mechanism than the explicit Partitioned attribute in the CHIPS specification.
Looking Ahead: The Future of Cross-Site State
As the web transitions away from traditional third-party cookies, partitioned cookies represent a middle groundβenabling legitimate cross-site functionality while eliminating the privacy risks of global identifiers. Understanding when and how to use the Partitioned attribute is becoming essential knowledge for web developers building embedded services, widgets, and cross-site integrations.
In the next section, we'll dive into the practical implementation details: how to set the Partitioned attribute correctly, what cookie characteristics are required, and how browsers determine partition keys when deciding which cookies to send with requests.
Implementing Partitioned Cookies with the Partitioned Attribute
Now that you understand why partitioned cookies exist, let's dive into the practical mechanics of implementing them. Setting a partitioned cookie requires specific syntax and understanding how the browser creates partition keys to isolate cookie storage.
Setting the Partitioned Attribute
To create a partitioned cookie, you add the Partitioned attribute to your Set-Cookie header. However, this attribute doesn't work aloneβit must be paired with the Secure attribute, meaning partitioned cookies can only be set over HTTPS connections.
Here's the basic syntax:
Set-Cookie: session_id=abc123; Secure; SameSite=None; Partitioned; Path=/
β οΈ Common Mistake 1: Attempting to set a partitioned cookie without Secure β οΈ
If you try Set-Cookie: id=xyz; Partitioned; SameSite=None, the browser will reject the cookie entirely. The Secure attribute is non-negotiable.
π― Key Principle: Partitioned cookies are inherently security-focused. The requirement for HTTPS ensures that partition boundaries can't be exploited through insecure connections.
Let's look at a complete, production-ready example. Imagine you're building an embedded chat widget that needs to maintain session state:
Set-Cookie: chat_session=user_7829;
Secure;
SameSite=None;
Partitioned;
Path=/;
Max-Age=2592000;
HttpOnly
Notice the inclusion of SameSite=None. While not strictly required for partitioned cookies to function, it's typically necessary because partitioned cookies are used in cross-site contexts. The HttpOnly flag adds additional security by preventing JavaScript access if you don't need it.
Understanding Partition Keys
The magic of partitioned cookies lies in how browsers create partition keys. A partition key is a tuple consisting of two components:
Partition Key = (Top-Level Site, Embedded Origin)
Top-Level Site: The site the user sees in their address bar
Embedded Origin: The origin setting the cookie
Let's visualize how this works with a concrete example:
Scenario 1: Your widget embedded on site-a.com
βββββββββββββββββββββββββββββββββββββββ
β Browser Address Bar β
β https://site-a.com β β Top-Level Site
βββββββββββββββββββββββββββββββββββββββ€
β β
β <iframe src="widget.example"> β β Embedded Origin
β Sets: session=abc; Partitioned β
β </iframe> β
β β
βββββββββββββββββββββββββββββββββββββββ
Partition Key: (site-a.com, widget.example)
Cookie Stored: session=abc
Scenario 2: Same widget embedded on site-b.com
βββββββββββββββββββββββββββββββββββββββ
β Browser Address Bar β
β https://site-b.com β β Different Top-Level Site
βββββββββββββββββββββββββββββββββββββββ€
β β
β <iframe src="widget.example"> β β Same Embedded Origin
β Sets: session=xyz; Partitioned β
β </iframe> β
β β
βββββββββββββββββββββββββββββββββββββββ
Partition Key: (site-b.com, widget.example)
Cookie Stored: session=xyz (separate storage!)
Notice that even though both cookies come from widget.example, they're stored separately because the top-level sites differ. This prevents widget.example from correlating user activity across site-a.com and site-b.com.
π‘ Mental Model: Think of partition keys like apartment buildings with numbered units. The building is your embedded origin, and the unit number is the top-level site. You can only access the items in "Building widget.example, Unit site-a.com"βnot the items in "Building widget.example, Unit site-b.com."
Reading Partitioned Cookies from JavaScript
When you access cookies through JavaScript's document.cookie API, partitioned cookies behave identically to regular cookies from the perspective of your embedded codeβbut crucially, you only see cookies for the current partition.
// In your embedded iframe at widget.example
// When loaded on site-a.com
console.log(document.cookie);
// Output: "session=abc; user_pref=dark_mode"
// The same code running when embedded on site-b.com
console.log(document.cookie);
// Output: "session=xyz; user_pref=light_mode"
There's no special API or flag to indicate a cookie is partitioned when reading itβthe browser automatically scopes your access based on the partition key of the current context.
β οΈ Common Mistake 2: Expecting to read cookies from other partitions β οΈ
Developers sometimes expect that they can access all partitions of their cookies. This defeats the entire purpose of partitioning. Each partition is completely isolated.
Migration Strategies
If you have existing third-party cookie implementations, migrating to CHIPS requires careful planning. Here's a practical migration strategy:
Phase 1: Dual-Write Approach
Initially, set both traditional and partitioned cookies:
Set-Cookie: session=abc123; Secure; SameSite=None; Path=/
Set-Cookie: session=abc123; Secure; SameSite=None; Partitioned; Path=/
Your server-side code should read cookies in this priority order:
- Check for partitioned cookie first
- Fall back to traditional cookie if partitioned isn't available
This ensures compatibility with browsers that don't yet support CHIPS while preparing for the future.
Phase 2: Detection and Analytics
Implement telemetry to understand what percentage of your traffic successfully uses partitioned cookies. You can detect support by checking if your partitioned cookie was actually set.
Phase 3: Partitioned-Only
Once traditional third-party cookies are deprecated (or your analytics show sufficient support), switch to partitioned-only.
π‘ Pro Tip: Use different cookie names for partitioned vs. traditional cookies during migration (e.g., session_p=abc for partitioned). This makes debugging significantly easier and prevents confusion in your server-side logic.
Testing and Debugging with DevTools
Modern browser DevTools provide specific support for inspecting partitioned cookies. In Chrome DevTools:
π§ Step-by-step debugging process:
- Open DevTools β Application tab β Cookies section
- Look for the Partition Key column (you may need to right-click the column headers and enable it)
- Partitioned cookies show their partition key; traditional cookies show "(not partitioned)"
- Check the Secure columnβall partitioned cookies must show a checkmark
π Quick Reference Card: DevTools Cookie Inspection
| Column | What to Check | Expected for Partitioned |
|---|---|---|
| π Secure | Must be checked | β Always Yes |
| π SameSite | Cross-site usage | Usually "None" |
| ποΈ Partition Key | Shows partition | "(top-site, origin)" |
| β° Expires | Lifetime | Your Max-Age value |
To test partition isolation, open your embedded content in two different top-level sites and verify that:
- Each shows different cookie values in DevTools
- Modifying a cookie in one partition doesn't affect the other
- The partition key column correctly identifies each partition
π€ Did you know? Some browsers show partitioned cookies with a special icon or color coding in DevTools to make them visually distinct from traditional cookies.
π‘ Real-World Example: When debugging a payment processing widget, developers discovered their partitioned cookies were being rejected on some pages. DevTools revealed those pages were still using HTTP (not HTTPS) for the iframe src, violating the Secure requirement. The fix was simple: ensure all iframe embeds use HTTPS URLs.
By mastering these implementation detailsβfrom setting the correct attributes to understanding partition keys and using DevTools effectivelyβyou'll be equipped to deploy partitioned cookies that preserve functionality while respecting user privacy.
Common Pitfalls and Best Practices for Partitioned Cookies
Implementing partitioned cookies correctly requires understanding several subtle requirements and constraints that differ from traditional third-party cookies. Let's explore the most common mistakes developers encounter and establish best practices for production deployments.
Mistake 1: Missing the Secure Requirement β οΈ
The most frequent error when implementing CHIPS is forgetting that partitioned cookies must be Secure. This requirement is non-negotiable and often catches developers off guard during local development.
β Wrong thinking: "I'll test partitioned cookies locally over HTTP first, then add HTTPS later."
β Correct thinking: "Partitioned cookies require HTTPS from day one. I need to set up local HTTPS or use a tunneling service for testing."
## This will FAIL - missing Secure attribute
Set-Cookie: session=abc123; Partitioned; Path=/; SameSite=None
## This will SUCCEED
Set-Cookie: session=abc123; Secure; Partitioned; Path=/; SameSite=None
π‘ Pro Tip: For local development, use tools like mkcert to generate trusted local SSL certificates, or use ngrok to tunnel your local server through HTTPS. Many modern frameworks also provide built-in HTTPS support for development mode.
Mistake 2: Misunderstanding Cookie Scope and Access Patterns β οΈ
A critical conceptual error involves misunderstanding how partitioned cookies are scoped. Developers often assume that setting a partitioned cookie on their domain means it will be accessible across all embedding contexts.
π― Key Principle: A partitioned cookie is tied to BOTH the cookie's domain AND the top-level site where it was created. This creates a partition key that determines access.
Scenario: analytics.example sets a partitioned cookie
Partition Key Structure:
(top-level-site, cookie-domain)
When embedded on shop.com:
Partition: (shop.com, analytics.example)
Cookie: user_id=123
When embedded on news.com:
Partition: (news.com, analytics.example)
Cookie: user_id=456 // DIFFERENT cookie!
Direct visit to analytics.example:
Partition: (analytics.example, analytics.example)
Cookie: user_id=789 // ANOTHER different cookie!
β Wrong thinking: "Once I set a partitioned cookie, it will be accessible whenever my domain is loaded, regardless of context."
β Correct thinking: "Each (top-level-site, my-domain) combination creates a completely separate cookie storage space."
π‘ Real-World Example: A payment widget from payments.example embedded on both store-a.com and store-b.com will maintain separate session cookies for each store, preventing any cross-site state leakage.
Mistake 3: Ignoring Storage Quota Implications β οΈ
Partitioned cookies introduce a significant change to browser storage management: cookies are now stored per-partition rather than per-domain. This has important implications for storage limits.
π€ Did you know? If your domain is embedded on 50 different top-level sites, you could theoretically have 50 different sets of cookies, multiplying your storage consumption by the number of embedding contexts.
Storage Considerations:
| Aspect | Traditional Cookies | Partitioned Cookies |
|---|---|---|
| ποΈ Storage scope | Per domain | Per (top-level, domain) pair |
| π Total storage | ~4KB per domain | ~4KB per partition |
| π’ Cookie count limit | ~180 per domain | ~180 per partition |
| πΎ Total potential | Limited to one domain | Multiplied by embedding sites |
β οΈ Common Mistake: Setting large partitioned cookies without considering that they'll be duplicated across many partitions.
Best Practice: Keep partitioned cookies minimal. Use them only for essential identifiers, not for storing large amounts of data. Consider this storage optimization:
## β BAD: Large cookie duplicated across partitions
Set-Cookie: user_prefs=theme:dark,lang:en,tz:UTC-5,notifications:on,layout:grid;
Secure; Partitioned; SameSite=None
## β
GOOD: Minimal identifier, load details from server
Set-Cookie: partition_id=x8f3k; Secure; Partitioned; SameSite=None
Mistake 4: Assuming Partitioned = SameSite=None β οΈ
Developers sometimes think partitioned cookies are simply a "new version" of SameSite=None cookies, but this fundamentally misunderstands their purpose.
Key Differences:
SameSite=None (Traditional Third-Party):
βββββββββββββββββββββββββββββββββββββββ
β analytics.example domain β
β ONE shared cookie across ALL sites β
β β
β shop.com βββ β
β news.com βββΌβββ [user_id=123] β
β blog.com βββ β
βββββββββββββββββββββββββββββββββββββββ
Partitioned (CHIPS):
βββββββββββββββββββββββββββββββββββββββ
β analytics.example domain β
β SEPARATE cookies per top-level β
β β
β shop.com β [user_id=abc] β
β news.com β [user_id=def] β
β blog.com β [user_id=ghi] β
βββββββββββββββββββββββββββββββββββββββ
π― Key Principle: Partitioned cookies prevent cross-site tracking by design. If your use case requires correlating user activity across multiple top-level sites, partitioned cookies won't workβand that's intentional.
Mistake 5: Failing to Implement Feature Detection β οΈ
Not all browsers support CHIPS yet, and failing to implement graceful degradation can break functionality for users on older browsers.
Best Practice: Feature Detection Pattern
// Server-side: Set both partitioned and traditional cookies
function setCrossStieToken(res, token) {
// Modern browsers with CHIPS support
res.cookie('embed_token', token, {
secure: true,
sameSite: 'none',
partitioned: true,
maxAge: 3600000
});
// Fallback for browsers without CHIPS
// (will be phased out as third-party cookies are deprecated)
res.cookie('embed_token_legacy', token, {
secure: true,
sameSite: 'none',
maxAge: 3600000
});
}
// Client-side: Check which cookie is available
function getEmbedToken() {
const cookies = document.cookie.split('; ');
const partitioned = cookies.find(c => c.startsWith('embed_token='));
const legacy = cookies.find(c => c.startsWith('embed_token_legacy='));
return partitioned || legacy || null;
}
π‘ Pro Tip: Monitor your analytics to track CHIPS adoption rates among your users. This data helps you determine when it's safe to remove fallback mechanisms.
Production Deployment Best Practices
π§ Implementation Checklist:
- β
Always set
Secure,Partitioned, andSameSite=Nonetogether - β Use HTTPS in all environments, including development
- β Keep cookie payloads minimal to manage storage multiplication
- β Implement feature detection and fallback strategies
- β Document the partition contexts where cookies are expected
- β Monitor cookie storage across different embedding scenarios
- β Test embedded functionality on multiple top-level domains
- β Plan for third-party cookie deprecation in your fallback strategy
π§ Mnemonic: HTTPS-MINI-TEST - HTTPS required, Minimal data, Independent partitions, No cross-site tracking, Implement detection, TEST across contexts.
Summary
You now understand the critical constraints and common mistakes surrounding partitioned cookies that many developers encounter in production:
π Quick Reference Card: CHIPS Pitfalls vs Best Practices
| β οΈ Pitfall | β Best Practice |
|---|---|
| π Testing over HTTP | π HTTPS required from day one; use local SSL tools |
| π Expecting global cookie access | π― Remember: one cookie per (top-level, domain) pair |
| πΎ Setting large cookie values | π¦ Minimal identifiers only; store data server-side |
| π Treating as SameSite=None replacement | π‘οΈ Understand: prevents tracking by design |
| π« No browser compatibility handling | π Implement feature detection and fallbacks |
β οΈ Critical Points to Remember:
- Partitioned cookies multiply your storage footprint across embedding contextsβdesign accordingly
- Each partition is completely isolatedβthis is a privacy feature, not a limitation to work around
- HTTPS is mandatoryβno exceptions, even in development
Practical Next Steps
π― Immediate Applications:
Audit your embedded widgets: Identify which components need cross-site cookies and migrate them to use the Partitioned attribute with proper fallbacks
Implement monitoring: Track cookie access patterns across partitions to understand your storage footprint and identify potential issues before users do
Prepare for third-party cookie deprecation: CHIPS is part of the Privacy Sandbox initiative. Begin transitioning away from traditional third-party cookies now, using partitioned cookies for legitimate embedded use cases while exploring alternatives like FedCM for authentication flows
By following these best practices and avoiding common pitfalls, you'll create robust, privacy-respecting embedded experiences that work reliably across modern browsers while gracefully degrading for older clients.