FreeToGenerate.com

Runs the algorithm the HTML Standard actually specifies, including the cases the RFC left open and the ones no reference table lists. Nothing is uploaded.

One header per line. The standard says a comma-separated value and several separate headers give the same result, so either form works here.

Try one:

The document sending the header.

One per line, innermost first: the page that embeds yours, then the page that embeds that, up to the browser tab. Leave empty for a page nobody is framing.

If an enforced policy carries a frame-ancestors directive, X-Frame-Options is ignored entirely — before its value is even read.

What a conformant browser does

The browser refuses to display it

The value is SAMEORIGIN, and an ancestor is a different origin. The check walks the whole chain, so one cross-origin frame anywhere in it is enough.

Values after splitting
sameorigin
First ancestor that is a different origin
https://widgets.partner.test

Every case the standard writes down

These are the values the HTML Standard publishes worked answers for, non-conformant ones included. The verdicts here are computed by this page rather than copied, evaluated against a same-origin parent.

Header valueValidResult
DENYOne valueYesThe browser refuses to display it
SAMEORIGINYesThe page is allowed to be embedded
INVALIDNoThe page is allowed to be embedded
ALLOWALLNoThe page is allowed to be embedded
ALLOW-FROM=https://example.com/NoThe page is allowed to be embedded
SAMEORIGIN, SAMEORIGINSeveral valuesNoThe page is allowed to be embedded
SAMEORIGIN, DENYNoThe browser refuses to display it
SAMEORIGIN,NoThe browser refuses to display it
SAMEORIGIN, ALLOWALLNoThe browser refuses to display it
SAMEORIGIN, INVALIDNoThe browser refuses to display it
ALLOWALL, INVALIDNoThe browser refuses to display it
ALLOWALL,NoThe browser refuses to display it
INVALID, INVALIDNoThe page is allowed to be embedded

Everything runs in your browser. Nothing is uploaded, and reloading the page forgets what you typed.

Also available in: Español · Português · Français · العربية

X-Frame-Options: what the header really does now

Paste your header and the frames around it, and see which step of the standard decides.

What is X-Frame-Options?

X-Frame-Options is a response header that tells a browser whether your page may be displayed inside someone else's frame. It exists to stop clickjacking: an attacker embeds your real page, makes it invisible, and lets a victim click a button they cannot see. Two values are meaningful — DENY refuses all framing, and SAMEORIGIN allows it only from your own origin.

The header is older than the process that usually produces web standards. Browsers shipped it around 2009, and the description everyone cites, RFC 7034, was written four years later to document what had already been built. That RFC is marked Informational, and says so about itself in its opening lines: it is not an Internet Standards Track specification.

Which means the document most pages link to is no longer the one that governs behaviour. The HTML Standard now carries the processing model and states plainly that its definition supersedes the RFC. The grammar it gives is shorter than the RFC's, the algorithm is more precise, and it settles several questions the RFC explicitly left open.

How to use it

  1. Enter your header. One per line if the response sends more than one. A comma-separated value and several separate headers are normatively equivalent, so either form gives the same answer here.
  2. Describe the frames around the page. Give the origin of the document sending the header, then the origins framing it, innermost first, up to the browser tab. This matters more than it looks: the check walks the entire chain.
  3. Add a Content-Security-Policy if you send one. If an enforced policy carries frame-ancestors, X-Frame-Options is ignored outright. Tick the Report-Only box to see the difference that makes, which is larger than most people expect.

The cases no reference table lists

The interesting behaviour is what happens when a response carries more than one value, which is common in practice because a proxy or a framework adds a header the application already set. The standard publishes a table of worked answers for exactly these cases, and the results are not what you would guess. SAMEORIGIN beside an invalid value blocks the page. Two invalid values allow it. The rule is deliberate: a header carrying one meaningful value and one confused one looks like a misconfiguration of something that was trying to work, so it is blocked on purpose, while a header that is entirely unparseable is treated as though it were never sent.

A trailing comma is enough to trigger it. Splitting on commas turns SAMEORIGIN, into two values, the second one empty, and that counts as a second distinct value — so the page is blocked. Sending SAMEORIGIN in one header and an empty X-Frame-Options in another does the same thing, for exactly the same reason.

ALLOWALL is the strangest survivor. It appears nowhere in RFC 7034 — it was never part of the header's documented grammar — yet the standard names it, purely so that it can be caught by the multiple-value rule. On its own it does nothing at all, and a page sending only ALLOWALL is as embeddable as one sending no header.

ALLOW-FROM is the one people still copy from tutorials. It is in the RFC's grammar, and the HTML Standard says in as many words that it is not to be implemented. A page relying on it to permit one specific partner is permitting everybody, silently, because a value the grammar does not admit is treated as no header at all.

The question the RFC left open

SAMEORIGIN sounds unambiguous and is not. Consider a page framed by a partner's widget, where that widget is itself framed by your own site at the top. Is the origin being compared the page immediately doing the framing, the top-level document in the tab, or every document in between? RFC 7034 admits all three readings in its own text, noting that the criteria may not be evaluated unanimously and listing each possibility.

The HTML Standard settles it: the check walks up the entire ancestor chain, and a single cross-origin document anywhere in it blocks the page. So the example above is refused, even though the top-level page is yours. That is the strictest of the three readings, and it is the one the tool above implements — which is why the default example looks as though it ought to be allowed and is not.

The other rule worth knowing is that a CSP frame-ancestors directive does not merely take priority, it removes X-Frame-Options from consideration entirely. The algorithm checks for the directive before it looks at the header's value at all, so a page sending DENY alongside any policy containing frame-ancestors is governed only by the policy. But this holds only for an enforced policy. A Content-Security-Policy-Report-Only header is skipped, because the algorithm considers only policies whose disposition is enforce — so moving frame-ancestors into Report-Only while you test it quietly hands control back to a header you may have stopped thinking about.

What this cannot tell you

It tells you what a conformant browser must do, not what any particular browser does. That distinction is real: the whole reason the RFC concedes an ambiguity is that implementations differed, and a browser can carry old behaviour for years. Nothing here has been measured against a shipping browser, and the browser support appendix in a document from 2013 is not evidence about today.

It also cannot see the page you are asking about. You supply the origins, so an answer is only as good as the chain you described — and the chain is exactly the part that is easy to get wrong, since a page can be framed by something you did not put there. If you want the real answer for a real page, the browser's own developer tools will tell you when a frame was refused, and why.

Finally, X-Frame-Options is the older half of a pair. Anything you can express with it, you can express with a CSP frame-ancestors directive, which also handles the cases the header cannot: allowing a specific origin, allowing several, or matching a scheme. The header is still worth sending for old clients, and the two coexist perfectly well, but a new deployment should be led by the policy rather than the header.

Why is it free?

Running an algorithm from a specification is arithmetic over a few strings, and it happens in your browser. There is no server in the loop, so there is nothing to bill for and no account to create.

Nothing is uploaded. The header and the origins you type never leave the tab.