X-Frame-Options
Clickjacking attacks exploit transparent iframes to capture unintended clicks. The X-Frame-Options response header prevents this by controlling whether a browser renders a page inside a frame, iframe, embed, or object element.
Note
The "X-" naming convention for HTTP headers, "X" referring to "experimental", has been deprecated and needs to be transitioned to the formal naming convention for HTTP headers. X-Frame-Options is registered in the IANA permanent message headers registry and is defined in the HTML specification. The prefix reflects its origins before formal standardization.
Note
The frame-ancestors directive in the
Content-Security-Policy
header supersedes X-Frame-Options. Sites supporting
modern browsers benefit from migrating to CSP
frame-ancestors. Many servers still send both headers
for backward compatibility.
Usage
Clickjacking attacks trick users into clicking hidden elements layered over a legitimate page. An attacker embeds the target site in a transparent iframe, positions a deceptive UI on top, and captures clicks intended for the framed content. X-Frame-Options prevents this by telling the browser whether the response is allowed to appear inside a frame.
Note
X-Frame-Options is deprecated in favor of
CSP frame-ancestors.
All modern browsers support frame-ancestors,
which offers more granular control including
multiple origins and scheme matching.
X-Frame-Options remains widely deployed for
backward compatibility with older browsers.
The header accepts two active values: DENY and
SAMEORIGIN. A third value, ALLOW-FROM, was defined in
earlier implementations but is now obsolete and ignored by
modern browsers.
Values
DENY
The DENY value blocks the page from being displayed in
any frame, regardless of the requesting site. No framing is
permitted under any circumstance.
SAMEORIGIN
The SAMEORIGIN value allows the page to be framed only by
pages sharing the same origin. A page on
https://example.re is allowed to frame another page from
https://example.re, but a page on a different origin is
blocked.
ALLOW-FROM (obsolete)
The ALLOW-FROM uri value once instructed the browser to
permit framing only from the specified URI. Modern browsers
no longer support this directive. The equivalent
functionality is available through the CSP frame-ancestors
directive:
Content-Security-Policy: frame-ancestors https://trusted.example.re
Example
Blocking all framing of a page, the strictest protection against clickjacking:
X-Frame-Options: DENY
Allowing same-origin framing while blocking external sites from embedding the page:
X-Frame-Options: SAMEORIGIN
A defense-in-depth configuration combining X-Frame-Options
with the CSP frame-ancestors directive for broad browser
coverage:
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
Troubleshooting
Framing issues show up as blank iframes or console errors when a page refuses to render inside another document.
"Refused to display in a frame" console error. The browser blocks the framed page and logs
Refused to display 'https://example.re/' in a frame because it set 'X-Frame-Options' to 'DENY'(or'SAMEORIGIN'). Check the response headers of the framed URL in the DevTools Network tab. If the page needs to be embedded, change the header value fromDENYtoSAMEORIGINor remove the header entirely and use CSPframe-ancestorsfor finer control.ALLOW-FROMnot working in modern browsers. TheALLOW-FROMdirective is obsolete. Chrome, Firefox, and Safari ignore the directive entirely, treating the header as if no valid value were set. ReplaceALLOW-FROMwith the CSPframe-ancestorsdirective, which supports multiple origins:Content-Security-Policy: frame-ancestors https://trusted.example.re https://other.example.re.Conflicting X-Frame-Options and CSP frame-ancestors. When both headers are present, browsers that support CSP Level 2 and later ignore X-Frame-Options and follow
frame-ancestorsonly. Older browsers that lack CSP support fall back to X-Frame-Options. Confirm the intended policy is consistent across both headers. SendingX-Frame-Options: DENYalongsideframe-ancestors 'self'creates a mismatch where modern browsers allow same-origin framing but legacy browsers block all framing.Legitimate embedding blocked (payment forms, widgets, embedded apps). Third-party services requiring iframe embedding fail when the host page sends
X-Frame-Options: DENY. Use CSPframe-ancestorsto allowlist specific origins that need embedding access:Content-Security-Policy: frame-ancestors 'self' https://payments.provider.example.re.Migrating from X-Frame-Options to CSP frame-ancestors. Deploy both headers during the transition period. Set
frame-ancestorsto match the intended framing policy. Keep X-Frame-Options for browsers without CSP support. Once legacy browser traffic drops below acceptable thresholds, remove X-Frame-Options and rely onframe-ancestorsalone. Test the migration by embedding the page in an iframe from an allowed origin and verifying the frame loads in multiple browsers.