frame-ancestors is a Content Security Policy directive that controls which sites are allowed to embed your page inside a <frame>, <iframe>, <object> or <embed>. It is the modern replacement for the older X-Frame-Options header and the standards-based way to defend against clickjacking. Setting frame-ancestors 'none' or frame-ancestors 'self' stops other sites from framing you at all.
What frame-ancestors does
Clickjacking works by loading your real page inside an invisible iframe on an attacker's site, then tricking a logged-in user into clicking something they can't see — a “delete account” button, a payment confirmation, a permission grant. The browser sends the click to your framed page with the user's real session, so it succeeds. The defence is simple: tell the browser who is allowed to frame you, and refuse everyone else.
frame-ancestors is a directive inside the Content-Security-Policy response header. It is enforced by the browser before it even renders your page in a frame: if the embedding (parent) origin isn't on your allow list, the browser blocks the frame from loading. Because it lives in CSP, it accepts a full source list — you can name specific trusted origins, not just an all-or-one choice.
Syntax and values
The directive takes a space-separated list of sources. The common shapes are:
# Nobody may frame this page — the strongest, most common choice
Content-Security-Policy: frame-ancestors 'none'
# Only your own origin may frame it (fine for same-site widgets/layouts)
Content-Security-Policy: frame-ancestors 'self'
# Your origin plus a named list of trusted partner origins
Content-Security-Policy: frame-ancestors 'self' https://partner.example.com https://*.trusted.dev'none'— no origin may embed the page. Equivalent in intent toX-Frame-Options: DENY. Use this for pages that should never be framed, which is most of them (login, dashboards, account settings).'self'— only pages served from the same origin may frame it. Roughly equivalent toX-Frame-Options: SAMEORIGIN.- An explicit origin list — e.g.
https://app.example.com https://*.partner.com. This is the pieceX-Frame-Optionscould never do: allow a specific set of external embedders.
Note the quotes: 'none' and 'self' are keywords and must be single-quoted, while concrete origins are written bare. See the MDN reference for CSP: frame-ancestors for the complete source-expression grammar.
How it supersedes X-Frame-Options
X-Frame-Options (XFO) was the first anti-framing header. It works, and browsers still honour it, but it is limited: it only understands DENY and SAMEORIGIN. There is no wildcard and no way to list several trusted origins — the old ALLOW-FROM value took a single origin and was never widely or consistently supported, so it is effectively dead. If you need “my site plus these two partners can frame me,” XFO simply cannot express it.
frame-ancestors replaces all of that with a proper source list, and the spec is explicit about precedence: when a page delivers both, the CSP frame-ancestors directive takes precedence and the browser ignores X-Frame-Options entirely. So the modern guidance from the OWASP Clickjacking Defense Cheat Sheet is to set frame-ancestors as your primary control, and optionally keep X-Frame-Options as a belt-and-braces fallback only for very old clients — knowing that any modern browser will use frame-ancestors and ignore the older header.
frame-ancestors is not covered by default-src. Most CSP directives fall back to default-src when omitted, but this one does not — if you don't write frame-ancestors explicitly, there is no framing protection from CSP no matter how strict your default-src is. Two more traps: X-Frame-Options can only name a single origin and has no wildcard, so it can't match the flexibility of a source list; and if you're unsure a policy is safe to enforce, ship it with Content-Security-Policy-Report-Only first to collect violation reports without breaking legitimate embeds.For the site owner and for the developer
For the site owner (plain English)
If you run a normal website and no one is supposed to embed your pages inside another site, you want the browser to refuse all framing. The fix is one HTTP header — Content-Security-Policy: frame-ancestors 'none' — and it's the same header a scanner checks for when it reports “missing clickjacking protection” or “no frame-ancestors / X-Frame-Options.” You don't need to touch your page content; your host, CDN, or developer adds it at the server or edge. If you're not sure whether your site is protected, the quickest answer is to scan it and look at the response headers.
Not sure if other sites can iframe your pages? Scan your headers — free and passive — to see whether frame-ancestors (or X-Frame-Options) is set.
Check your security headers →For the developer (exact syntax)
Send the header on every HTML response. The raw header is:
Content-Security-Policy: frame-ancestors 'none'Server and platform snippets:
# nginx — add to the server / location block
add_header Content-Security-Policy "frame-ancestors 'none'" always;# Apache (.htaccess or vhost, mod_headers)
Header always set Content-Security-Policy "frame-ancestors 'none'"// Cloudflare — Transform Rule (Modify Response Header → Set static)
// Header name: Content-Security-Policy
// Value: frame-ancestors 'none'
// Cloudflare Workers — set it on the response instead
export default {
async fetch(request, env, ctx) {
const res = await fetch(request);
const out = new Response(res.body, res);
out.headers.set("Content-Security-Policy", "frame-ancestors 'none'");
return out;
},
};// Next.js — next.config.js / next.config.mjs
const nextConfig = {
async headers() {
return [
{
source: "/:path*",
headers: [
{ key: "Content-Security-Policy", value: "frame-ancestors 'none'" },
],
},
];
},
};
module.exports = nextConfig;If you already send a larger CSP, add frame-ancestors as one directive among the others — separate directives with semicolons, for example default-src 'self'; frame-ancestors 'none'. And if some pages do need to be embedded by a known partner, swap 'none' for a source list like frame-ancestors 'self' https://partner.example.com rather than dropping the directive.
frame-ancestors is the framing control inside a broader Content Security Policy. It is the modern successor to the header covered in clickjacking and X-Frame-Options, and it's one of the core headers in the HTTP security headers guide.