Cross-Origin-Embedder-Policy (COEP)
Only lets your page load cross-origin resources that explicitly allow it. Needed, with COOP, for cross-origin isolation.
Updated 3 November 2026
Check your site's COEP header
We send one normal request (following redirects) and grade the Cross-Origin-Embedder-Policy header on the final response.
Recommended value
Cross-Origin-Embedder-Policy: credentialless
| Value / directive | What it does |
|---|---|
| unsafe-none | Default. Any cross-origin resource may load. |
| require-corp | Cross-origin resources must send Cross-Origin-Resource-Policy or be loaded with CORS. |
| credentialless | No-CORS cross-origin requests are sent without cookies, so they may load without CORP. Easier with third-party images. |
When you need COEP
Most sites do not. COEP exists so a page can become cross-origin isolated (together with Cross-Origin-Opener-Policy: same-origin). Isolation is required for SharedArrayBuffer, precise performance.now() timers and some WebAssembly threading features. If you do not use those, leave COEP unset.
require-corp vs credentialless
require-corp blocks every cross-origin image, script or font that does not send Cross-Origin-Resource-Policy: cross-origin (or is fetched with CORS). Third-party resources you do not control often break.
credentialless loads such resources but strips cookies from the request, so they cannot carry user data. It is usually the easier option. Roll out with Cross-Origin-Embedder-Policy-Report-Only first to see what would break.
How to set Cross-Origin-Embedder-Policy
nginx
# inside your server { } block
add_header Cross-Origin-Embedder-Policy "credentialless" always;
Apache
# .htaccess or virtual host (needs mod_headers)
Header always set Cross-Origin-Embedder-Policy "credentialless"
Laravel middleware
// app/Http/Middleware/SecurityHeaders.php
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
$response->headers->set('Cross-Origin-Embedder-Policy', 'credentialless');
return $response;
}
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->append(\App\Http\Middleware\SecurityHeaders::class);
})
Express (Node.js)
app.use((req, res, next) => {
res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless');
next();
});
// or: app.use(require('helmet')()) for a sensible default set
Cloudflare
Rules → Transform Rules → Modify Response Header → Create rule.
Match: all incoming requests (or your hostname).
Then: Set static → Header name: Cross-Origin-Embedder-Policy → Value: credentialless
In nginx, an add_header inside a location block discards every add_header inherited from the server block. Repeat your security headers there, or use an include file. The always flag also sends the header on error responses.
Common mistakes
-
Adding
require-corpsite-wide "for security" and breaking third-party images, fonts and embeds. - Setting COEP without COOP and expecting cross-origin isolation.
FAQ
Do I need Cross-Origin-Embedder-Policy?
Only if you need cross-origin isolation, for SharedArrayBuffer or high-precision timers. Otherwise it is optional.
What is the difference between require-corp and credentialless?
require-corp blocks cross-origin resources that do not opt in. credentialless loads them without cookies.
Related guides
Headers are one of 30+ things attackers check
The free StackShield scan also checks for exposed .env files, debug mode, leaked tooling, weak TLS and more, from the outside, in about a minute.
Run a free scan