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 / directiveWhat 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-corp site-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.

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