Cross-Origin Isolation Checker Guide: Check COOP and COEP Together

Some browser features are powerful enough that browsers refuse to offer them to ordinary pages. High-resolution timers, shared memory between threads, and similar capabilities can be abused to measure tiny timing differences and infer data from other origins, in a class of attack known as Spectre-style side-channel attacks. Browsers therefore gate those features behind a state called cross-origin isolation, which a page only enters when it proves, through its headers, that it has opted into a stricter separation from other origins. Isolation is not a single switch. It is the combined effect of two headers, and understanding that pairing is the whole point of this guide.

The Cross-Origin Isolation Checker tool checks pasted headers for cross-origin isolation. As with the other checkers in this series, it works on the text you paste, not on a live request to your site. You paste a set of response headers, and the tool reports whether the set qualifies the page for isolation. That distinction between a paste and a live response matters more here than usual, because isolation affects what the page can do at runtime. A paste that qualifies tells you the header set is correctly drafted; it does not tell you the live server sends those headers, and it does not tell you the page actually behaves as isolated in a visitor's browser. Both of those need their own confirmation.

The two headers in the pair each do a different job. Cross-Origin-Opener-Policy, or COOP, controls the browsing context group: it decides whether this page shares a browsing context group with pages that opened it or that it opens, which determines whether one page can hold a reference to another's window object. The usual value is same-origin, which isolates the top-level page from cross-origin popups. Cross-Origin-Embedder-Policy, or COEP, controls which cross-origin resources the page may load, as described in the COEP guide: require-corp blocks non-opted-in resources, while credentialless loads them without credentials. Only when both headers are present with valid values does the browser consider the page cross-origin isolated. Either header on its own leaves the page unisolated, however correct that single header may be.

There is a further detail worth knowing before you read a result. Isolation also depends on the responses of embedded resources in some cases, and on the browser itself: older browsers may not support these headers at all, in which case they are ignored and the page is simply not isolated there. That is a graceful outcome rather than an error, but it means isolation is a property you verify per browser, not a universal guarantee. A page that is isolated in a current browser may be unisolated in an older one, and features gated behind isolation should therefore degrade gracefully rather than failing hard when isolation is absent.

A worked example you can follow

Take a sample pasted header set containing 4 headers: a content type header, a cache header, a COOP header reading same-origin, and a COEP header reading require-corp. Count the isolation headers first: 2 present. Count the isolation headers required: 2. So 2 divided by 2 is 100 percent present, and both values are recognised, so this set qualifies for isolation. The arithmetic is deliberately simple, because the rule is deliberately strict: the page is isolated, and gated features become available.

Now remove the COEP header from the sample, leaving 3 headers, of which only 1 is an isolation header. That is 1 divided by 2, or 50 percent present. It is tempting to read that as half isolated, but the browser does not work that way. Isolation is binary: with COEP missing, the page is 0 percent isolated in practical terms, and gated features stay unavailable. The same is true in reverse: a perfect COEP header with no COOP header also yields no isolation. This all-or-nothing behaviour is the single most common misunderstanding about these headers, and it is why checking the pair together, rather than each header separately, is the right habit.

Take a third sample where both headers are present but the COOP value reads same-origin-allow-popups. The count is again 2 out of 2, but the value changes the meaning: same-origin-allow-popups keeps isolation while allowing the page to retain references to popups it opens, which is a deliberate relaxation for pages that need popup communication. The set still qualifies, but the isolation is weaker in one specific respect, and that trade-off should be a conscious choice, not an accident of copying a value from an example. If the page opens no popups, same-origin is the simpler choice; if it does, the allow-popups variant is the one to test. In both cases, re-check the full set after any edit, and confirm the count returns to 2 out of 2 with values you can explain.

Mistakes to avoid

The first mistake is checking one header and assuming isolation follows. Always count both headers, and treat 1 out of 2 as a failing result, not a partial pass. The second mistake is pasting headers from the wrong response, such as a stylesheet or an image, and concluding something about the document. Isolation is judged on the top-level document response, so paste that response's headers. The third mistake is enabling isolation without testing the page's real embeds and workers. Strict values can block third-party resources and break features that worked before, and that breakage should be found in testing, not by visitors. The fourth mistake is treating a pasted-header pass as a live-site guarantee. Confirm the served headers on the deployed site, and confirm the isolated state in a real browser, before announcing that a feature now works.

The Cross-Origin Embedder Policy Checker tool reads the COEP half on its own, and the Cross-Origin Opener Policy Checker tool reads the COOP half. For background on placing these headers in a wider security review, see Reading a Security Headers Report, Line by Line.

Checking the result before you rely on it

Treat a qualifying paste as the start of verification, not the end. Serve both headers, load the page in a current browser, confirm the isolated state through the browser's own reporting, and exercise the features that need isolation alongside the page's ordinary embeds. Keep a note of the two values you shipped and the reason for each, because a future edit that drops one header will silently unisolate the page, and the note is what makes that regression visible. Isolation that is counted, confirmed live, and tested against real content is a genuine security improvement; isolation claimed from a single pasted header is only a hope.