Headers

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 breaksWhyFix
Google OAuth popupCOOP same-origin blocks cross-origin window accessSwitch to redirect flow instead of popup
Stripe.js iframesCOEP require-corp blocks resources without CORP headerUse COEP: credentialless instead
Google FontsFonts do not have CORP headerSelf-host fonts or use credentialless
Third-party imagesCDN images without CORP header are blockedAdd 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
Check if your domain is on the HSTS preload list → HSTS Preload Checker