← Docs

X-Frame-Options Reference

DENY, SAMEORIGIN, ALLOW-FROM -- what each directive does, browser support, and how to set the header on your stack.

X-Frame-Options is an HTTP response header that tells a browser whether a page may be rendered inside a <frame>, <iframe>, <embed>, or <object>. It is the original defense against clickjacking, introduced by Microsoft in Internet Explorer 8. The header has since been obsoleted by the Content Security Policy frame-ancestors directive, but it remains widely used and widely supported. For most sites, shipping both headers together is still a reasonable baseline.

The header accepts a single directive value. Two of them work everywhere. The third does not work at all in any modern browser. Each is documented below.

DENY

DENY blocks all framing. The page cannot be embedded by any other page, including pages on your own origin. Per MDN, the browser refuses to render the document in a frame regardless of who is attempting to frame it.

X-Frame-Options: DENY

This is the correct choice for most sites. If a page has no legitimate reason to appear inside an iframe -- which is true of the vast majority of pages -- DENY is the strictest and safest setting.

SAMEORIGIN

SAMEORIGIN allows framing only by pages served from the same origin as the framed page. A page can embed itself; a page on any other origin cannot embed it.

X-Frame-Options: SAMEORIGIN

Choose this when your own application frames its own pages -- dashboards embedding widgets, live previews inside an editor, page builders that render your content in an iframe.

Note that subdomains are different origins: https://app.example.com and https://admin.example.com cannot frame each other under SAMEORIGIN. If you need cross-subdomain framing, use CSP frame-ancestors with explicit origins instead.

ALLOW-FROM

ALLOW-FROM was intended to allow framing by a single specified origin, so that one trusted partner site could embed your page while everyone else was blocked.

X-Frame-Options: ALLOW-FROM https://trusted.example.com

Do not use this directive. It is obsolete. It was never supported in Chrome or Safari, and Firefox dropped support in version 70 (October 2019). Per MDN, modern browsers that encounter a response header with this directive will ignore the header completely -- meaning a page with ALLOW-FROM ends up with no framing protection at all.

Never ship ALLOW-FROM. Because browsers ignore the entire header when they see it, using ALLOW-FROM is worse than shipping nothing. Use CSP frame-ancestors https://partner.com to allow specific origins.

Browser support

BrowserDENY / SAMEORIGINALLOW-FROM
ChromeYesNever supported
FirefoxYesDropped in v70
SafariYesNever supported
EdgeYesNever supported
Internet ExplorerIE8+IE8+ (legacy only)

Source: MDN and CanIUse, July 2026. DENY and SAMEORIGIN are supported everywhere the header exists. ALLOW-FROM is not usable in any current browser. Internet Explorer supported ALLOW-FROM from IE8 until its end of life, but IE is no longer a supported browser.

How to set X-Frame-Options

The header must be set on the HTTP response by your server, CDN, or application framework. The one-liners below get you started; each links to a full configuration guide where available.

PlatformSnippet
NGINXadd_header X-Frame-Options "DENY" always;
ApacheHeader always set X-Frame-Options "DENY"
CloudflareTransform Rules → Set X-Frame-Options: DENY
WordPressheader('X-Frame-Options: DENY');
Express.jsres.setHeader('X-Frame-Options', 'DENY');
IIS&lt;add name="X-Frame-Options" value="DENY" /&gt;

The meta tag that does not work

A common mistake is trying to set the header from HTML with a <meta> tag:

<!-- This has no effect. Do not do this. -->
<meta http-equiv="X-Frame-Options" content="deny">

X-Frame-Options is only honored when delivered as an HTTP response header. Browsers ignore it when it appears in a <meta> tag. The same is true of CSP frame-ancestors -- it also cannot be set via a meta tag. If you need framing protection, configure your server or CDN to emit real HTTP headers.

frame-ancestors: the modern replacement

X-Frame-Options has been obsoleted by the Content Security Policy frame-ancestors directive. frame-ancestors has been Baseline Widely Available since January 2018 and covers everything XFO can do, plus more:

  • frame-ancestors 'none' is similar to XFO DENY.
  • frame-ancestors 'self' is similar to XFO SAMEORIGIN.
  • It supports multiple explicit origins -- the thing ALLOW-FROM promised but never delivered.
  • It checks every ancestor in a nested frame chain, not just the immediate parent.
Content-Security-Policy: frame-ancestors 'self' https://trusted.example.com

default-src does not fall back to frame-ancestors. You must set frame-ancestors explicitly. A policy of default-src 'self' does nothing to prevent clickjacking.

When both headers are present and the browser supports CSP, an enforced frame-ancestors directive takes precedence over X-Frame-Options. If the two policies conflict, the CSP directive wins. A Content-Security-Policy-Report-Only header does not override X-Frame-Options -- only an enforced policy does. In browsers that do not support CSP, X-Frame-Options remains the sole protection, which is why shipping both headers is still a reasonable baseline.

Shipping XFO alongside CSP as a legacy fallback is fine, provided the two agree. For most sites:

Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY

Test your site now →