X-Frame-Options is an HTTP response header that controls whether a browser is allowed to render a page inside a <frame>, <iframe>, or <object>. It is the original defense against clickjacking attacks, and while still widely deployed, its role is now filled more completely by the CSP frame-ancestors directive.
Clickjacking works by embedding a target site in a transparent iframe layered over a decoy page. The user believes they are clicking on something harmless — a game button, a prize claim — but their click lands on the invisible target, triggering actions like social media likes, transfers, or permission grants on their behalf. The attack is silent and requires no malware on the victim's device.
X-Frame-Options blocks the framing step entirely. A browser that receives this header will refuse to display the page inside another page's frame, so the overlay trick never gets off the ground.
X-Frame-Options: DENY X-Frame-Options: SAMEORIGIN
A third value, ALLOW-FROM uri, was intended to whitelist a specific origin. It is obsolete and ignored by all modern browsers. Do not rely on it.
The Content Security Policy frame-ancestors directive supersedes X-Frame-Options. It supports the same 'none' and 'self' values, but also allows you to specify multiple trusted origins — something ALLOW-FROM could never do reliably.
Content-Security-Policy: frame-ancestors 'none' Content-Security-Policy: frame-ancestors 'self' https://partner.example.com
When both frame-ancestors and X-Frame-Options are present, browsers that support CSP Level 2 or later give precedence to frame-ancestors and ignore X-Frame-Options. Older browsers fall back to X-Frame-Options. This is why many sites send both headers: frame-ancestors 'none' alongside X-Frame-Options: DENY for broad compatibility.
Any page that performs state-changing actions on behalf of the authenticated user is a candidate for clickjacking. Account settings, payment flows, permission dialogs, and administrative interfaces should all set DENY unless there is a specific reason to allow embedding. Static content pages with no interactive controls carry less risk, but setting the header costs nothing in those cases either.
frame-ancestors instead.X-Frame-Options leaves no fine-grained allowlist option and no protection in contexts where XFO is ignored. Pair both for defense in depth.Audit X-Frame-Options with the headers tool
Open Headers Tool