# frame-ancestors (/en/docs/web-security/policies/content-security-policy/directives/frame-ancestors)



The `frame-ancestors` directive controls which origins are allowed to embed the
current page inside a
[`<frame>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/frame),
[`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/iframe),
`<object>`, or `<embed>`. It is the modern defense against clickjacking, where an
attacker loads your page in a hidden frame on their own site and tricks a user
into clicking something they cannot see.

Note that this directive is about who can frame you, the reverse of
[`frame-src`](/en/docs/web-security/policies/content-security-policy/directives/frame-src),
which controls what your page is allowed to load into its own frames.

Prevent any site, including your own, from framing the page:

```http
Content-Security-Policy: frame-ancestors 'none'
```

## Fallback chain [#fallback-chain]

`frame-ancestors` has no fallback.
[`default-src`](/en/docs/web-security/policies/content-security-policy/directives/default-src)
does not cover it, so a page with no `frame-ancestors` can be framed by anyone.

## Values [#values]

`frame-ancestors` takes a source list of origins. Nonces and hashes do not apply,
they describe content, not an embedding origin.

| Value                 | Status | Description                                                                                                                                                                                                                                                         |
| --------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `'none'`              | ✅ Good | No origin may embed the page, including the same origin.                                                                                                                                                                                                            |
| `'self'`              | ✅ Good | Only the page's own origin may embed it.                                                                                                                                                                                                                            |
| Host or scheme source | ✅ Good | Allows the listed [host source](/en/docs/web-security/policies/content-security-policy/values/csp-host-source) or [scheme source](/en/docs/web-security/policies/content-security-policy/values/csp-scheme-source) to embed the page, for example a partner domain. |

You can list several ancestors. When the embedding chain does not match, the
browser refuses to render the page in the frame. Avoid a wildcard or a bare
scheme like `https:`, which lets any site frame your page and reopens the
clickjacking risk; list only the specific origins that have a real reason to
embed you.

### Relationship to X-Frame-Options [#relationship-to-x-frame-options]

`frame-ancestors` is the successor to the legacy
[`X-Frame-Options`](/en/docs/web-security/security-headers/x-frame-options)
header, and it is more expressive. The mapping is direct:

| X-Frame-Options             | frame-ancestors equivalent                |
| --------------------------- | ----------------------------------------- |
| `DENY`                      | `frame-ancestors 'none'`                  |
| `SAMEORIGIN`                | `frame-ancestors 'self'`                  |
| `ALLOW-FROM uri` (obsolete) | `frame-ancestors https://partner.example` |

Where a browser supports both, `frame-ancestors` takes precedence over
`X-Frame-Options`. `X-Frame-Options` could never list more than one allowed origin
and its `ALLOW-FROM` form was dropped, so `frame-ancestors` replaces it. You can
still send `X-Frame-Options` alongside for very old clients, but `frame-ancestors`
is the control that matters today. We cover when to retire the legacy header in
[clickjacking protection without a CSP header](/en/blog/frame-ancestors-without-csp-header)
and in [legacy security headers to retire](/en/blog/legacy-security-headers-to-retire).

## Examples [#examples]

Allow only same-origin framing:

```http
Content-Security-Policy: frame-ancestors 'self'
```

Allow a specific partner to embed the page:

```http
Content-Security-Policy: frame-ancestors 'self' https://partner.example.com
```

## Security notes [#security-notes]

`frame-ancestors` works only as an HTTP response header. A `<meta http-equiv>` CSP
cannot carry it, the browser ignores it there. The same is true of
[`sandbox`](/en/docs/web-security/policies/content-security-policy/directives/sandbox)
and the reporting directives. Set `frame-ancestors` in your server or edge
configuration, not in markup.

The directive blocks clickjacking. In a clickjacking attack the victim's browser
loads your real, logged-in page in a transparent frame layered over attacker
content, so a click the user thinks lands on the attacker's button actually lands
on your page (confirming a transfer, changing a setting, granting a permission).
By restricting who may frame the page, you stop the page from rendering inside an
attacker's document at all, which removes the attack surface.

## Known bypasses and risks [#known-bypasses-and-risks]

`frame-ancestors` only governs framing. It does nothing about other navigation or
script behavior, so it is one control among several in a complete policy. It also
relies on the response actually carrying the header on every framed document, a
page served without it from some path or cache can still be framed, so apply it
consistently across the site.

Setting `frame-ancestors 'none'` on a page that is supposed to be embedded (a
widget, an OAuth consent screen, a documentation snippet) breaks that embedding.
Decide per page whether it should ever be framed, and by whom, then set the
directive to match. Run the policy through the
[CSP evaluator](/tools/csp-evaluator) to confirm the value is what you intend.

## Recommendation [#recommendation]

Ship `frame-ancestors 'none'` on pages that are never meant to be embedded, or
`'self'` if you frame your own pages, per the [OWASP CSP cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html).

```http
Content-Security-Policy: frame-ancestors 'none'
```

```http
X-Frame-Options: DENY
```

The [OWASP HTTP Headers cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html)
recommends sending `X-Frame-Options: DENY` alongside for old clients;
`frame-ancestors` takes precedence wherever both are supported.

## Reporting [#reporting]

When the directive blocks a framing attempt, the browser emits a
[`csp-violation` report](/en/docs/web-security/reporting-api/reports/csp-violation)
naming `frame-ancestors` as the effective directive. Wire delivery with the
[`report-to` directive](/en/docs/web-security/policies/content-security-policy/directives/report-to)
and the [`Reporting-Endpoints` header](/en/docs/web-security/reporting-api/headers/reporting-endpoints).

## Browser support [#browser-support]

`frame-ancestors` is part of CSP Level 2 and Level 3 and is widely supported
across current browsers. Where supported it supersedes `X-Frame-Options`.

## FAQ [#faq]

### Should I use X-Frame-Options or frame-ancestors? [#should-i-use-x-frame-options-or-frame-ancestors]

`frame-ancestors` is the modern, more expressive successor to `X-Frame-Options`,
and it wins wherever both are supported. Send both: `frame-ancestors` as the
control that matters today, and `X-Frame-Options: DENY` alongside for very old
clients. See the full comparison in
[X-Frame-Options vs frame-ancestors](/en/blog/x-frame-options-vs-frame-ancestors).

### Can I set frame-ancestors in a meta tag? [#can-i-set-frame-ancestors-in-a-meta-tag]

No. `frame-ancestors` works only as an HTTP response header. A `<meta
http-equiv>` CSP cannot carry it, and the browser ignores it there, the same as
the `sandbox` and reporting directives. Set it in your server or edge
configuration on every framed document, not in the page markup.

### frame-ancestors 'none' or 'self'? [#frame-ancestors-none-or-self]

`'none'` blocks all framing, including same-origin, so use it on pages that are
never meant to be embedded. `'self'` allows only the page's own origin to frame
it, so use it when you embed your own pages. Any other origin listed must have a
real reason to embed you.

## See also [#see-also]

* [X-Frame-Options header](/en/docs/web-security/security-headers/x-frame-options)
* [frame-src](/en/docs/web-security/policies/content-security-policy/directives/frame-src)
* [sandbox](/en/docs/web-security/policies/content-security-policy/directives/sandbox)
* [default-src](/en/docs/web-security/policies/content-security-policy/directives/default-src)
* [clickjacking protection without a CSP header](/en/blog/frame-ancestors-without-csp-header)
* [Legacy security headers to retire](/en/blog/legacy-security-headers-to-retire)

## Sources [#sources]

* [MDN, CSP frame-ancestors](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-ancestors)
* [MDN, X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Frame-Options)
* [W3C, Content Security Policy Level 3](https://www.w3.org/TR/CSP3/)
* [OWASP, HTTP Headers cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html)
