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.

  1. "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 from DENY to SAMEORIGIN or remove the header entirely and use CSP frame-ancestors for finer control.

  2. ALLOW-FROM not working in modern browsers. The ALLOW-FROM directive is obsolete. Chrome, Firefox, and Safari ignore the directive entirely, treating the header as if no valid value were set. Replace ALLOW-FROM with the CSP frame-ancestors directive, which supports multiple origins: Content-Security-Policy: frame-ancestors https://trusted.example.re https://other.example.re.

  3. 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-ancestors only. Older browsers that lack CSP support fall back to X-Frame-Options. Confirm the intended policy is consistent across both headers. Sending X-Frame-Options: DENY alongside frame-ancestors 'self' creates a mismatch where modern browsers allow same-origin framing but legacy browsers block all framing.

  4. 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 CSP frame-ancestors to allowlist specific origins that need embedding access: Content-Security-Policy: frame-ancestors 'self' https://payments.provider.example.re.

  5. Migrating from X-Frame-Options to CSP frame-ancestors. Deploy both headers during the transition period. Set frame-ancestors to 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 on frame-ancestors alone. Test the migration by embedding the page in an iframe from an allowed origin and verifying the frame loads in multiple browsers.

See also

Last updated: April 4, 2026