Making your website "cross-origin isolated" using COOP and COEP  |  Articles  |  web.dev Skip to main content Resources Web Platform Dive into the web platform, at your pace. HTML CSS JavaScript User experience Learn how to build better user experiences. Performance Accessibility Identity Learn Get up to speed on web development. Learn HTML Learn CSS Learn JavaScript Learn AI Learn Performance Learn Accessibility More courses Additional resources Explore content collections, patterns, and more. AI and the web Explore PageSpeed Insights Patterns Podcasts & shows Developer Newsletter About web.dev Discover Baseline How to use Baseline Blog Case Studies / English Deutsch Español – América Latina Français Indonesia Italiano Polski Português – Brasil Tiếng Việt Türkçe Русский עברית العربيّة فارسی हिंदी বাংলা ภาษาไทย 中文 – 简体 中文 – 繁體 日本語 한국어 Sign in Articles AI and the web Fast load times Learn Core Web Vitals Identity Progressive Web Apps Payments Notifications How to optimize INP Network reliability React Animations Mini apps Media Safe and secure WebAssembly Devices Easily discoverable Test automation Angular Resources More AI and the web Fast load times Learn Core Web Vitals Identity Progressive Web Apps Payments Notifications How to optimize INP Network reliability React Animations Mini apps Media Safe and secure WebAssembly Devices Easily discoverable Test automation Angular Discover Baseline How to use Baseline Blog Case Studies Understand security basics Security should not be so scary! What are security attacks? Understanding "same-site" and "same-origin" Security headers quick reference Secure connections with HTTPS Why HTTPS matters Enabling HTTPS on your servers What is mixed content? Fixing mixed content When to use HTTPS for local development How to use HTTPS for local development Prevent info leaks Browser sandbox Same-origin policy Cross-Origin Resource Sharing (CORS) Making your website "cross-origin isolated" using COOP and COEP Why you need "cross-origin isolated" for powerful features Protect your resources from web attacks with Fetch Metadata Protect websites from XSS Prevent DOM-based cross-site scripting vulnerabilities with Trusted Types Mitigate cross-site scripting (XSS) with a strict Content Security Policy (CSP) Securely hosting user data in modern web applications Protect users from tracking Understanding cookies SameSite cookies explained SameSite cookie recipes First-party cookie recipes Referer and Referrer-Policy best practices User-agent client hints Schemeful Same-Site Monitor security violations and deprecations Reporting API Migrate to Reporting API v1 Network Error Logging (NEL) Help! I've been hacked Help, I think I've been hacked How do I know if my site was hacked? Top ways sites get hacked by spammers Build a support team Quarantine your site Use Search Console Assess spam damage Fix the Japanese Keyword hack Fix the gibberish hack Fix the cloaked keywords and links hack Hacked with malware Identify the vulnerability Clean and maintain your site Request a review Glossary for hacked sites FAQ for hacked sites Web Platform HTML CSS JavaScript User experience Performance Accessibility Identity Learn Learn HTML Learn CSS Learn JavaScript Learn AI Learn Performance Learn Accessibility More courses Additional resources AI and the web Explore PageSpeed Insights Patterns Podcasts &amp; shows Developer Newsletter About web.dev Home Articles Resources Safe and secure Making your website "cross-origin isolated" using COOP and COEP Stay organized with collections Save and categorize content based on your preferences. Use COOP and COEP to set up a cross-origin isolated environment and enable powerful features like SharedArrayBuffer, performance.measureUserAgentSpecificMemory() and high resolution timer with better precision. Eiji Kitamura X GitHub Mastodon Bluesky Caution: SharedArrayBuffer on Chrome desktop requires cross-origin isolation starting from Chrome 92. Learn more at SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92. Updates June 21, 2022: Worker scripts also need care when cross-origin isolation is enabled. Added some explanations. Aug 5, 2021: JS Self-Profiling API has been mentioned as one of APIs that require cross-origin isolation, but reflecting recent change of the direction, it's removed. May 6, 2021: Based on feedback and issues reported we've decided to adjust the timeline for SharedArrayBuffer usage in none cross-origin isolated sites to be restricted in Chrome M92. April 16, 2021: Added notes about a new COEP credentialless mode and COOP same-origin-allow-popups to be a relaxed condition for cross-origin isolation. March 5, 2021: Removed limitations for SharedArrayBuffer, performance.measureUserAgentSpecificMemory(), and debugging functionalities, which are now fully enabled in Chrome 89. Added upcoming capabilities, performance.now() and performance.timeOrigin, that will have higher precision. February 19, 2021: Added a note about feature policy allow="cross-origin-isolated" and debugging functionality on DevTools. October 15, 2020: self.crossOriginIsolated is available from Chrome 87. Reflecting that, document.domain is immutable when self.crossOriginIsolated returns true. performance.measureUserAgentSpecificMemory() is ending its origin trial and is enabled by default in Chrome 89. Shared Array Buffer on Android Chrome will be available from Chrome 88. Some web APIs increase the risk of side-channel attacks like Spectre. To mitigate that risk, browsers offer an opt-in-based isolated environment called cross-origin isolated. With a cross-origin isolated state, the webpage will be able to use privileged features including: API Description SharedArrayBuffer Required for WebAssembly threads. This is available from Android Chrome 88. Desktop version is currently enabled by default with the help of Site Isolation, but will require the cross-origin isolated state and will be disabled by default in Chrome 92. performance.measureUserAgentSpecificMemory() Available from Chrome 89. performance.now(), performance.timeOrigin Currently available in many browsers with the resolution limited to 100 microseconds or higher. With cross-origin isolation, the resolution can be 5 microseconds or higher. Features that will be available behind cross-origin isolated state. The cross-origin isolated state also prevents modifications of document.domain. (Being able to alter document.domain allows communication between same-site documents and has been considered a loophole in the same-origin policy.) To opt in to a cross-origin isolated state, you need to send the following HTTP headers on the main document: Cross-Origin-Embedder-Policy: require-corp Cross-Origin-Opener-Policy: same-origin These headers instruct the browser to block loading of resources or iframes which haven't opted into being loaded by cross-origin documents, and prevent cross-origin windows from directly interacting with your document. This also means those resources being loaded cross-origin require opt-ins. You can determine whether a web page is in a cross-origin isolated state by examining self.crossOriginIsolated. This article shows how to use these new headers. In a follow-up article I will provide more background and context. Note: This article is aimed at those who would like to get their websites ready for using SharedArrayBuffer, WebAssembly threads, performance.measureUserAgentSpecificMemory() or high resolution timer with better precision in a more robust manner across browser platforms. Key term: This article uses many similar-sounding terminologies. To make things clearer, let's define them first: * COEP: Cross Origin Embedder Policy * COOP: Cross Origin Opener Policy * CORP: Cross Origin Resource Policy * CORS: Cross Origin Resource Sharing * CORB: Cross Origin Read Blocking Deploy COOP and COEP to make your website cross-origin isolated Note: Learn practical steps to enable cross-origin isolation at A guide to enable cross-origin isolation. Integrate COOP and COEP 1. Set the Cross-Origin-Opener-Policy: same-origin header on the top-level document By enabling COOP: same-origin on a top-level document, windows with the same origin, and windows opened from the document, will have a separate browsing context group unless they are in the same origin with the same COOP setting. Thus, isolation is enforced for opened windows and mutual communication between both windows is disabled. Caution: This will break integrations that require cross-origin window interactions such as OAuth and payments. To mitigate this problem, we are exploring relaxing the condition to enable cross-origin isolation to Cross-Origin-Opener-Policy: same-origin-allow-popups. This way the communication with the window opened by itself will be possible. If you want to enable cross-origin isolation but are blocked by this issue, we recommend registering for an origin trial and waiting until the new condition is available. We are not planning to terminate the origin trial until this issue is safely resolved. A browsing context group is a set of windows that can reference each other. For example, a top-level document and its child documents embedded via <iframe>. If a website (https://a.example) opens a popup window (https://b.example), the opener window and the popup window share the same browsing context, therefore they have access to each other via DOM APIs such as window.opener. You can check if the window opener and its openee are in separate browsing context groups from DevTools. Try it: See the impact of different COOP parameters. 2. Ensure resources have CORP or CORS enabled Make sure that all resources in the page are loaded with CORP or CORS HTTP headers. This step is required for step four, enabling COEP. Here is what you need to do depending on the nature of the resource: If the resource is expected to be loaded only from the same origin, set the Cross-Origin-Resource-Policy: same-origin header. If the resource is expected to be loaded only from the same site but cross origin, set the Cross-Origin-Resource-Policy: same-site header. If the resource is loaded from cross origin(s) under your control, set the Cross-Origin-Resource-Policy: cross-origin header if possible. For cross origin resources that you have no control over: Use the crossorigin attribute in the loading HTML tag if the resource is served with CORS. (For example, <img src="***" crossorigin>.) Ask the owner of the resource to support either CORS or CORP. For iframes, follow the same principles above and set the Cross-Origin-Resource-Policy: cross-origin (or same-site, same-origin depending on the context). Scripts loaded with a WebWorker must be served from same-origin, so you don't need a CORP or CORS headers. For a document or a worker served with COEP: require-corp, cross-origin subresources loaded without CORS must set the Cross-Origin-Resource-Policy: cross-origin header to opt into being embedded. For example, this applies to <script>, importScripts, <link>, <video>, <iframe>, etc. You can enable cross-origin isolation on a document embedded within an iframe by applying allow="cross-origin-isolated" permissions policy to the <iframe> tag and meeting the same conditions described in this document. Note that entire chain of the documents including parent frames and child frames must be cross-origin isolated as well. Key term: It's important that you understand the difference between "same-site" and "same-origin". Learn about the difference at Understanding same-site and same-origin. 3. Use the COEP Report-Only HTTP header to assess embedded resources Before fully enabling COEP, you can do a dry run by using the Cross-Origin-Embedder-Policy-Report-Only header to examine whether the policy actually works. You will receive reports without blocking embedded content. Recursively apply this to all documents including the top-level document, iframes and worker scripts. For information on the Report-Only HTTP header, see Observe issues using the Reporting API. 4. Enable COEP Once you've confirmed that everything works, and that all resources can be successfully loaded, switch the Cross-Origin-Embedder-Policy-Report-Only header to the Cross-Origin-Embedder-Policy header with the same value to all documents including those that are embedded via iframes and worker scripts. Try it: See the impact of different COEP / CORP parameters. Note: Squoosh (an image optimization PWA) now uses COOP / COEP to gain access to Wasm Threads (and Shared Array Buffer) as well on Android Chrome. Caution: We've been exploring ways to deploy Cross-Origin-Resource-Policy at scale, as cross-origin isolation requires all subresources to explicitly opt-in. And we have come up with the idea of going in the opposite direction: a new COEP "credentialless" mode that allows loading resources without the CORP header by stripping all their credentials. We hope this will lighten your burden of making sure the subresources are sending the Cross-Origin-Resource-Policy header. However, since credentialless mode is available on Chrome from version 96 but not supported by any other browsers yet, some developers might find it challenging to deploy COOP or COEP. If you prefer not to enable cross-origin isolation yet, we recommend registering for an origin trial and waiting until credentialless is available in more browsers. Determine whether isolation succeeded with self.crossOriginIsolated The self.crossOriginIsolated property returns true when the web page is in a cross-origin isolated state and all resources and windows are isolated within the same browsing context group. You can use this API to determine whether you have successfully isolated the browsing context group and gained access to powerful features like performance.measureUserAgentSpecificMemory(). Debug issues using Chrome DevTools For resources that are rendered on the screen such as images, it's fairly easy to detect COEP issues because the request will be blocked and the page will indicate a missing image. However, for resources that don't necessarily have a visual impact, such as scripts or styles, COEP issues might go unnoticed. For those, use the DevTools Network panel. If there's an issue with COEP, you should see (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep) in the Status column. You can then click the entry to see more details. You can also determine the status of iframes and popup windows through the Application panel. Go to the "Frames" section on the left hand side and expand "top" to see the breakdown of the resource structure. You can check the iframe's status such as availability of SharedArrayBuffer, etc. You can also check the popup windows's status such as whether it's cross-origin isolated. Observe issues using the Reporting API The Reporting API is another mechanism through which you can detect various issues. You can configure the Reporting API to instruct your users' browser to send a report whenever COEP blocks the loading of a resource or COOP isolates a pop-up window. Chrome has supported the Reporting API since version 69 for a variety of uses including COEP and COOP. Note: Are you already using the Reporting API with the Report-To header? Chrome is transitioning to a new version of the Reporting API, which replaces Report-To with Reporting-Endpoints; consider migrating to the new version. Check out Migrate to Reporting API v1 for details. To learn how to configure the Reporting API and set up a server to receive reports, head over to Using the Reporting API. Example COEP report An example COEP report payload when cross-origin resource is blocked looks like this: [{ "age": 25101, "body": { "blocked-url": "https://third-party-test.glitch.me/check.svg?", "blockedURL": "https://third-party-test.glitch.me/check.svg?", "destination": "image", "disposition": "enforce", "type": "corp" }, "type": "coep", "url": "https://cross-origin-isolation.glitch.me/?coep=require-corp&coop=same-origin&", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4249.0 Safari/537.36" }] Caution: blocked-url is there for backward compatibility only and will be removed eventually. Example COOP report An example COOP report payload when a pop-up window is opened isolated looks like this: [{ "age": 7, "body": { "disposition": "enforce", "effectivePolicy": "same-origin", "nextResponseURL": "https://third-party-test.glitch.me/popup?report-only&coop=same-origin&", "type": "navigation-from-response" }, "type": "coop", "url": "https://cross-origin-isolation.glitch.me/coop?coop=same-origin&", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36" }] When different browsing context groups try to access each other (only on "report-only" mode), COOP also sends a report. For example, a report when postMessage() is attempted would look like this: [{ "age": 51785, "body": { "columnNumber": 18, "disposition": "reporting", "effectivePolicy": "same-origin", "lineNumber": 83, "property": "postMessage", "sourceFile": "https://cross-origin-isolation.glitch.me/popup.js", "type": "access-from-coop-page-to-openee" }, "type": "coop", "url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36" }, { "age": 51785, "body": { "disposition": "reporting", "effectivePolicy": "same-origin", "property": "postMessage", "type": "access-to-coop-page-from-openee" }, "type": "coop", "url": "https://cross-origin-isolation.glitch.me/coop?report-only&coop=same-origin&", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36" }] Conclusion Use a combination of COOP and COEP HTTP headers to opt a web page into a special cross-origin isolated state. You will be able to examine self.crossOriginIsolated to determine whether a web page is in a cross-origin isolated state. We'll keep this post updated as new features are made available to this cross-origin isolated state, and further improvements are made to DevTools around COOP and COEP. Resources Why you need "cross-origin isolated" for powerful features A guide to enable cross-origin isolation SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92 Monitor your web page's total memory usage with measureUserAgentSpecificMemory() Previous arrow_back Cross-Origin Resource Sharing (CORS) Next Why you need "cross-origin isolated" for powerful features arrow_forward Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates. Last updated 2020-04-13 UTC. [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2020-04-13 UTC."],[],[]] web.dev web.dev We want to help you build beautiful, accessible, fast, and secure websites that work cross-browser, and for all of your users. This site is our home for content to help you on that journey, written by members of the Chrome team, and external experts. Contribute File a bug See open issues Related Content Chrome for Developers Chromium updates Case studies Podcasts & shows Follow @ChromiumDev on X YouTube Chrome for Developers on LinkedIn RSS Terms Privacy Manage cookies English Deutsch Español – América Latina Français Indonesia Italiano Polski Português – Brasil Tiếng Việt Türkçe Русский עברית العربيّة فارسی हिंदी বাংলা ภาษาไทย 中文 – 简体 中文 – 繁體 日本語 한국어