COOP and COEP Headers for SharedArrayBuffer — Cross-Origin Isolation
Updated April 2026
Reading this? Verify your fix live. Scan your headers → HeadersFixer
SharedArrayBuffer, performance.now() with microsecond precision, and WebAssembly threads all require cross-origin isolation. Without it, browsers disable them. Cross-origin isolation is enabled by two headers: COOP and COEP.
Cross-origin isolation is required for: SharedArrayBuffer, Atomics.wait(), high-resolution timers, WebAssembly threads, and some GPU APIs. If you are building a video editor, audio worklet, or WASM-heavy app, you need this.
Check if your page is cross-origin isolated
// In browser console console.log(crossOriginIsolated); // true = isolated, false = not isolated // If false, SharedArrayBuffer will throw: // TypeError: SharedArrayBuffer is not defined (or not constructable)
The two headers you need
# COOP — controls popup window access Cross-Origin-Opener-Policy: same-origin # COEP — controls which cross-origin resources can load Cross-Origin-Embedder-Policy: require-corp # or the easier option: Cross-Origin-Embedder-Policy: credentialless
Config by stack
Nginx
add_header Cross-Origin-Opener-Policy "same-origin" always; add_header Cross-Origin-Embedder-Policy "require-corp" always;
Vercel (vercel.json)
{ "headers": [{ "source": "/(.*)", "headers": [ { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" }, { "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" } ] }]
}
Express
app.use((req, res, next) => { res.setHeader("Cross-Origin-Opener-Policy", "same-origin"); res.setHeader("Cross-Origin-Embedder-Policy", "require-corp"); next();
});
What breaks — and how to fix it
| What breaks | Why | Fix |
|---|---|---|
| Google OAuth popup | COOP same-origin blocks cross-origin window access | Switch to redirect flow instead of popup |
| Stripe.js iframes | COEP require-corp blocks resources without CORP header | Use COEP: credentialless instead |
| Google Fonts | Fonts do not have CORP header | Self-host fonts or use credentialless |
| Third-party images | CDN images without CORP header are blocked | Add crossorigin="anonymous" and use credentialless |
COEP: credentialless — the easier path
If you cannot control all cross-origin resources (third-party images, fonts, scripts), use credentialless instead of require-corp. Resources load without cookies — most CDN content works fine:
Cross-Origin-Embedder-Policy: credentialless # Supported in: Chrome 96+, Edge 96+, Firefox 119+ # Not supported: Safari (as of early 2026)
Mark your own cross-origin resources
If you use require-corp, every cross-origin resource your page loads must opt in with a CORP header:
# On your API or asset server Cross-Origin-Resource-Policy: cross-origin # allow any origin Cross-Origin-Resource-Policy: same-site # allow same-site only Cross-Origin-Resource-Policy: same-origin # allow same-origin only
Test cross-origin isolation
// After adding headers, test in browser console: console.log(crossOriginIsolated); // must be true // Or check with curl: curl -I https://yourapp.com/ | grep -i "cross-origin"Scan your headers → HeadersFixer