X-Frame-Options vs. CSP frame-ancestors
Both can restrict who embeds your page. CSP gives you an allowlist, while X-Frame-Options offers a simpler legacy policy.
The quick comparison
| Intent | X-Frame-Options | CSP frame-ancestors |
|---|---|---|
| Block all framing | DENY | 'none' |
| Same origin only | SAMEORIGIN | 'self' |
| Allow a partner | No reliable modern allowlist | https://partner.example |
Which header takes precedence?
When an enforced CSP includes frame-ancestors, modern browsers use it instead of X-Frame-Options. A CSP without frame-ancestors does not replace X-Frame-Options for this purpose. A report-only policy does not enforce restrictions.
Multiple enforced CSP policies are applied together. Adding a permissive policy does not relax a stricter policy already sent by your CDN or application. Every policy must permit the embed.
Allow a trusted parent
Set an HTTP response header on the page being embedded:
Content-Security-Policy: frame-ancestors 'self' https://app.exampleThis permits same-origin framing and the specified HTTPS parent. Origins include the scheme, hostname, and port: https://app.example and http://app.example are different origins. Wildcard subdomains such as https://*.example.com do not also match the apex https://example.com.
If the page is nested inside several iframes, every ancestor must match. Checking only the immediate parent can miss the reason for a browser block.
Common configuration mistakes
- Using
ALLOW-FROM, an obsolete X-Frame-Options value that modern browsers do not reliably support. - Putting frame-ancestors in an HTML meta tag. This directive must be delivered in an HTTP response header.
- Assuming
default-src 'none'prohibits other sites from framing the page. frame-ancestors has no default-src fallback. - Confusing
frame-srcwith frame-ancestors. frame-src governs what your page embeds; frame-ancestors governs who embeds your page.
Check your deployment, not just your config
A reverse proxy or CDN may add, remove, or duplicate headers. Inspect the final response after redirects using the header checker, then verify in your actual parent page. Keep older-client compatibility needs in mind if you send both headers.
References: MDN X-Frame-Options and MDN frame-ancestors.