Chrome is phasing out support for third-party cookies and partitioning storage to reduce cross-site tracking. This poses a challenge for sites and services that rely on cookies and other storage in embedded contexts, for user journeys such as authentication. The Storage Access API (SAA) allows these use cases to continue to work, while limiting cross-site tracking as much as possible.
Implementation status
The Storage Access API is available in all major browsers, but there are slight implementation differences between browsers. These differences have been highlighted in the relevant sections in this post.
Work is continuing to resolve all remaining blocking issues, before standardizing the API.
What is the Storage Access API?
The Storage Access API is a JavaScript API that allows iframes to request storage access permissions when access would otherwise be denied by browser settings. Embeds with use cases that depend on loading cross-site resources can use the API to request access permission from the user, on an as-needed basis.
If the storage request is granted, then the iframe will have access to its unpartitioned cookies and storage, which are also available when users visit it as a top-level site.
The Storage Access API allows specific unpartitioned cookie and storage access to be provided with minimal burden to the end user, while still preventing generic unpartitioned cookie and storage access as is often used for user tracking.
Use cases
Some third-party embeds require access to unpartitioned cookies or storage to provide a better experience to the user—something that won't be available after third-party cookies have been deprecated and storage partitioning is enabled.
Use cases include:
- Embedded commenting widgets which require login session details.
- Social media "Like" buttons which require login session details.
- Embedded documents which require login session details.
- A premium experience provided to a video embed (for example, to not show ads for logged in users, or to know the user's preferences for closed captions or restrict certain video types).
- Embedded payment systems.
Many of these use cases involve persisting login access in embedded iframes.
When to use the Storage Access API over other APIs
The Storage Access API is one of the alternatives to using unpartitioned cookies and storage, so it is important to understand when to use this API compared to the others. It's meant for use cases where both the following are true:
- The user will interact with the embedded content—that is, it is not a passive iframe or a hidden iframe.
- The user has visited the embedded origin in a top-level context—that is, when that origin is not embedded in another site.
There are alternative APIs for a variety of use cases:
- Cookies Having Independent Partitioned State (CHIPS) allows developers to opt-in a cookie to "partitioned" storage, with a separate cookie jar per top-level site. For example, a third-party web-chat widget may rely on setting a cookie to save session information. The session information is saved per-site, so the cookie set by the widget doesn't need to be accessed on other websites where it is also embedded. The Storage Access API is useful when an embedded third-party widget is dependent on sharing the same information across different origins (for example for logged-in session details or preferences).
- Storage Partitioning is a way for cross-site iframes to use existing JavaScript storage mechanisms while dividing the underlying storage per-site. This prevents embedded storage in one website from being accessed by the same embed on other websites.
- Related Websites Sets (RWS) is a way for an organization to declare relationships among sites, so that browsers allow limited unpartitioned cookie and storage access for specific purposes. Sites still need to request access with the Storage Access API, but for sites within the set, access can be granted without user prompts.
- Federated Credential Management (FedCM) is a privacy-preserving approach to federated identity services. The Storage Access API deals with accessing unpartitioned cookies and storage post-login. For some use cases FedCM provides an alternative solution to the Storage Access API, and may be preferable as it features a more login-oriented browser prompt. However, adopting FedCM usually requires additional changes to your code, for example to support its HTTP endpoints.
- Anti-fraud, ad-related, and measurement APIs also exist, and the Storage Access API is not intended to address those concerns.
Use the Storage Access API
The Storage Access API has two promised-based methods:
Document.hasStorageAccess()
(also available under the new nameDocument.hasUnpartitionedCookieAccess()
as of Chrome 125)Document.requestStorageAccess()
It also integrates with the Permissions API. This lets you check the status of the storage-access permission in a third-party context, which indicates whether a call to document.requestStorageAccess()
would be automatically granted:
Use the hasStorageAccess()
method
When a site first loads, it can use the hasStorageAccess()
method to check whether access to third-party cookies has already been granted.
// Set a hasAccess boolean variable which defaults to false.
let hasAccess = false;
async function handleCookieAccessInit() {
if (!document.hasStorageAccess) {
// Storage Access API is not supported so best we can do is
// hope it's an older browser that doesn't block 3P cookies.
hasAccess = true;
} else {
// Check whether access has been granted using the Storage Access API.
// Note on page load this will always be false initially so we could be
// skipped in this example, but including for completeness for when this
// is not so obvious.
hasAccess = await document.hasStorageAccess();
if (!hasAccess) {
// Handle the lack of access (covered later)
}
}
if (hasAccess) {
// Use the cookies.
}
}
handleCookieAccessInit();
Storage access is only granted to an iframe document after it calls requestStorageAccess(),
so hasStorageAccess()
will always return false initially—except when another same-origin document in the same iframe had already been granted access. The grant is preserved across same-origin navigations inside the iframe specifically to allow reloads after granting access for pages that require cookies to be present in the initial request for the HTML document.
Use requestStorageAccess()
If the iframe does not have access it may need to request access using the requestStorageAccess()
method:
if (!hasAccess) {
try {
await document.requestStorageAccess();
} catch (err) {
// Access was not granted and it may be gated behind an interaction
return;
}
}
The first time this is requested, the user may need to approve this access with a browser prompt, after which the promise will resolve, or will reject resulting in an exception if await
is used.
To prevent abuse, this browser prompt will only be shown after a user interaction. That's why requestStorageAccess()
initially needs to be called from a user-activated event handler, rather than immediately as the iframe loads:
async function doClick() {
// Only do this extra check if access hasn't already been given
// based on the hasAccess variable.
if (!hasAccess) {
try {
await document.requestStorageAccess();
hasAccess = true; // Can assume this was true if requestStorageAccess() did not reject.
} catch (err) {
// Access was not granted.
return;
}
}
if (hasAccess) {
// Use the cookies
}
}
document.querySelector('#my-button').addEventListener('click', doClick);
If you need to use local storage instead of cookies, you could do the following:
let handle = null;
async function doClick() {
if (!handle) {
try {
handle = await document.requestStorageAccess({localStorage: true});
} catch (err) {
// Access was not granted.
return;
}
}
// Use handle to access unpartitioned local storage.
handle.localStorage.setItem('foo', 'bar');
}
document.querySelector('#my-button').addEventListener('click', doClick);
Permission prompts
When the user clicks the button for the first time, the browser prompt will automatically appear, typically in the address bar. The following screenshot shows an example of Chrome's prompt, but other browsers have a similar UI:
![Chrome Storage Access API permission prompt](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/storage-access-api-permission-prompt.png?authuser=3)
The prompt may be skipped by the browser and permission automatically provided in certain circumstances:
- If the page and iframe have been used in the last 30 days after accepting the prompt.
- If the embedded iframe is part of a Related Website Set.
- In Firefox, the prompt is also skipped for known websites (those you have interacted with at the top level) for the first five attempts.
Alternatively, the method may be automatically rejected without showing the prompt in certain circumstances:
- If the user has not previously visited and interacted with the site that owns the iframe as a top-level document, not in an iframe. This means the Storage Access API is only useful for embedded sites that users have previously visited in a first-party context.
- If the
requestStorageAccess()
method is called outside of a user interaction event without prior approval of the prompt after an interaction.
While the user will be prompted on the initial use, subsequent visits can resolve requestStorageAccess()
without a prompt and without requiring user interaction in Chrome and Firefox. Note that Safari always requires a user interaction.
As cookie and storage access may be granted without a prompt, or user interaction, it is often possible to get unpartitioned cookie or storage access before a user interaction on browsers that support this (Chrome and Firefox) by calling requestStorageAccess()
on page load. This may allow you to access unpartitioned cookies and storage immediately and provide a fuller experience, even before the user interacts with the iframe. This can be a better user experience for some situations than waiting for user interaction.
Use the storage-access
permission query
To check whether access can be granted without a user interaction, you can check the status of the storage-access
permission and only make the requestStoreAccess()
call early if no user action is required, rather than call it and have it fail when an interaction is required.
This also lets you potentially handle the need for a prompt upfront by displaying different content—for example, a login button.
The following code adds the storage-access
permission check to the earlier example:
// Set a hasAccess boolean variable which defaults to false except for
// browsers which don't support the API - where we assume
// such browsers also don't block third-party cookies.
let hasAccess = false;
async function hasCookieAccess() {
// Check if Storage Access API is supported
if (!document.requestStorageAccess) {
// Storage Access API is not supported so best we can do is
// hope it's an older browser that doesn't block 3P cookies.
return true;
}
// Check if access has already been granted
if (await document.hasStorageAccess()) {
return true;
}
// Check the storage-access permission
// Wrap this in a try/catch for browsers that support the
// Storage Access API but not this permission check
// (e.g. Safari and earlier versions of Firefox).
let permission;
try {
permission = await navigator.permissions.query(
{name: 'storage-access'}
);
} catch (error) {
// storage-access permission not supported. Assume no cookie access.
return false;
}
if (permission) {
if (permission.state === 'granted') {
// Permission has previously been granted so can just call
// requestStorageAccess() without a user interaction and
// it will resolve automatically.
try {
await document.requestStorageAccess();
return true;
} catch (error) {
// This shouldn't really fail if access is granted, but return false
// if it does.
return false;
}
} else if (permission.state === 'prompt') {
// Need to call requestStorageAccess() after a user interaction
// (potentially with a prompt). Can't do anything further here,
// so handle this in the click handler.
return false;
} else if (permission.state === 'denied') {
// Not used: see https://github.com/privacycg/storage-access/issues/149
return false;
}
}
// By default return false, though should really be caught by earlier tests.
return false;
}
async function handleCookieAccessInit() {
hasAccess = await hasCookieAccess();
if (hasAccess) {
// Use the cookies.
}
}
handleCookieAccessInit();
Sandboxed iframes
When using the Storage Access API in sandboxed iframes, the following sandbox permissions are required:
allow-storage-access-by-user-activation
is required to allow access to the Storage Access API.allow-scripts
is required to allow use of JavaScript to call the API.allow-same-origin
is required to allow access to same-origin cookies and other storage.
For example:
<iframe sandbox="allow-storage-access-by-user-activation
allow-scripts
allow-same-origin"
src="..."></iframe>
Cookie requirements
To be accessed with the Storage Access API in Chrome, cross-site cookies must be set with the following two attributes:
SameSite=None
- which is required to mark the cookie as cross-siteSecure
- which ensures only cookies set by HTTPS sites can be accessed.
In Firefox and Safari, cookies are defaulted to SameSite=None
and they don't restrict SAA to Secure
cookies so these attributes are not required. It is recommended to be explicit about the SameSite
attribute and to always use Secure
cookies.
Top-level page access
The Storage Access API is intended for enabling access to third-party cookies within embedded iframes.
There are also other use cases when the top-level page requires access to third-party cookies. For example, images or scripts which are restricted by cookies, which site owners may want to include directly in the top-level document rather than in an iframe. To address this use case Chrome has proposed an extension to the Storage Access API which adds arequestStorageAccessFor()
method.
The requestStorageAccessFor()
method
requestStorageAccessFor()
method works in a similar way to requestStorageAccess()
but for top-level resources. It can only be used for sites within a Related Website Set to prevent granting general access to third-party cookies.
For more details on how to use requestStorageAccessFor()
read the Related Website Sets: developer guide.
The top-level-storage-access
permission query
Browser Support
Similar to the storage-access
permission, there is a top-level-storage-access
permission to check whether access can be granted for requestStorageAccessFor()
.
How is the Storage Access API different when used with RWS?
When Related Website Sets are used with the Storage Access API, certain additional capabilities are available as detailed in the following table:
Without RWS | With RWS | |
---|---|---|
Requires a user gesture to initiate the request for storage access | ||
Requires user to visit requested storage origin in a top-level context before granting access | ||
First time user prompt can be skipped | ||
requestStorageAccess not required to be called if access has been previously granted |
||
Automatically grants access across other domains in a Related Website Site | ||
Supports requestStorageAccessFor for top-level page access |
Demo: setting and accessing cookies
The following demo shows how a cookie set by yourself in the first screen of the demo can be accessed in an embedded frame in the second site of the demo:
storage-access-api-demo.glitch.me
The demo requires a browser with third-party cookies disabled:
- Chrome 118 or higher with the
chrome://flags/#test-third-party-cookie-phaseout
flag set and browser restarted. - Firefox
- Safari
Demo: setting Local Storage
The following demo shows how to access unpartitioned Broadcast Channels from a third-party iframe using the Storage Access API:
https://saa-beyond-cookies.glitch.me/
The demo requires Chrome 125 or higher with the test-third-party-cookie-phaseout flag enabled.
Resources
- Read the specification providing third-party cookie access or follow and raise issues.
- Read the specification providing unpartitioned storage access or follow and raise issues.
- API documentation and guide.
- Chrome documentation on using Storage Access API in Related Website Sets