Back to the header reference
Isolation

X-Frame-Options

Send `X-Frame-Options: DENY` to stop other sites embedding your pages in a frame — but set CSP `frame-ancestors` as well, which supersedes it.

Situational

Correct for some sites and disruptive for others. Read what it breaks before deploying.

What it does

Clickjacking works by loading your page in a transparent frame over an attacker's page, so a user who thinks they are clicking "Play" is actually clicking "Delete account" on your site, with their own session. X-Frame-Options was the original defence: it tells the browser whether your page may be framed at all.

It is a blunt instrument, and deliberately so. The header takes `DENY` or `SAMEORIGIN` and nothing more useful — the `ALLOW-FROM <origin>` value that appears in a great deal of copy-pasted configuration was never implemented in Chrome or Safari, and has been removed from Firefox. A config using it is, in practice, sending an invalid value that browsers ignore, which means no protection at all.

CSP `frame-ancestors` replaced it and does the job properly: it accepts a list of origins, it is part of a header you are probably already sending, and where both headers are present browsers honour `frame-ancestors`. Sending both remains the pragmatic choice — X-Frame-Options costs one line and covers clients or scanners that only look for it.

What to send

X-Frame-Options: DENY

Unless your pages are meant to be embedded, `DENY` is correct and `SAMEORIGIN` is a weaker default that exists mostly for applications framing their own pages. If you do need specific partners to embed you, that requirement cannot be expressed here at all — use CSP `frame-ancestors https://partner.example.com`, and keep `DENY` off.

Directives and values

DENY

No site may frame this page, including your own. The right default for anything with a session behind it.

SAMEORIGIN

Only pages from the same origin may frame it. Note that this historically compared against the top-level document rather than the immediate parent in some browsers, which made nested-frame bypasses possible.

ALLOW-FROM <origin>

Never implemented in Chrome or Safari, removed from Firefox. Sending it yields no protection in any current browser. Use CSP `frame-ancestors` instead.

Common mistakes

  1. Using ALLOW-FROM to permit a partner. No current browser implements it. The config looks deliberate, the scanner may even report the header as present, and the page is framable by anyone. `frame-ancestors` is the only working way to allow specific origins.
  2. Setting it in a <meta> tag. X-Frame-Options is only honoured as an HTTP response header. The meta-equivalent is ignored entirely — the browser has to know whether to render before it has parsed the document.
  3. Sending conflicting values from app and proxy. A framework that sets `SAMEORIGIN` behind a proxy that adds `DENY` produces a duplicated header, and browser behaviour when the values disagree is inconsistent. Decide in one place.
  4. Assuming it protects an API response. It governs framing of documents. It does nothing for a JSON endpoint, and it is not a substitute for CSRF tokens or `SameSite` cookies, which address a different attack.

Browser support

Supported everywhere, but only for `DENY` and `SAMEORIGIN`. Every current browser prefers CSP `frame-ancestors` when both are present, so treat X-Frame-Options as the compatibility layer and `frame-ancestors` as the policy.

Frequently asked questions

Should I use DENY or SAMEORIGIN for X-Frame-Options?

Use `DENY` unless your application genuinely frames its own pages, in which case use `SAMEORIGIN`. If specific third-party origins need to embed you, neither value can express that — set CSP `frame-ancestors` with the permitted origins instead.

Why does ALLOW-FROM not work?

It was never implemented in Chrome or Safari and has been removed from Firefox. Browsers that do not recognise the value treat the header as invalid and apply no framing restriction, so a page relying on it is fully framable. CSP `frame-ancestors` is the supported replacement.

Do I still need X-Frame-Options if I have CSP frame-ancestors?

Not for protection in current browsers, which prefer `frame-ancestors` where both are present. It is still worth sending as a one-line fallback for old clients and because many compliance scanners check for it specifically.

Does X-Frame-Options stop CSRF?

No. It prevents your page being framed, which addresses clickjacking. Cross-site request forgery is a different attack that submits requests without framing anything, and is addressed by anti-CSRF tokens and `SameSite` cookie attributes.

Check this header on your own site

The free Security Headers Checker reads X-Frame-Options from a live response and grades it alongside every other header on this reference — no account needed.

For the longer treatment, read HTTP Security Headers: HSTS, CSP, X-Frame-Options & More in the Learning Center.

Related headers