X-Frame-Options on 27 homepages: 16 send it, 5 contradict their own CSP
X-Frame-Options came back from 16 of 27 homepages read on 2026-09-02. Twelve of the same 27 send a CSP frame-ancestors directive, eight send both headers, and on five of those eight the two headers describe different rules.

FIELD TEST · 2026-09-02 · 27 homepages · one request each · X-Frame-Options and CSP frame-ancestors
Sample and method: 30 homepages fetched once each on 2026-09-02 with a desktop Chrome user agent, redirects followed, no JavaScript executed. Three dropped out — stackoverflow.com and medium.com returned 403, www.reddit.com returned an 8,393-byte shell — leaving 27. We read the response headers of the final URL only.
Sixteen of 27 homepages read on 2026-09-02 sent an X-Frame-Options header. Twelve sent a Content-Security-Policy containing frame-ancestors, the directive the W3C says obsoletes it. Eight sites sent both, and on five of those eight the two headers describe different rules. Seven sites sent neither.
How we measured it
One GET per site, desktop Chrome user agent rather than Googlebot, redirects followed, one attempt each. Every count below comes from the headers on the final response — nothing was rendered and no browser was involved. Our exit node sits in Osaka, Japan, which matters for any site that varies headers by region.
Two headers were read: X-Frame-Options, and Content-Security-Policy searched for the substring frame-ancestors. A policy sent as Content-Security-Policy-Report-Only was counted separately; exactly one site in the batch sent one, and it carried no framing directive, so it changes none of the numbers.
# The same two reads on one of your own pages
curl -sIL -A 'Mozilla/5.0' https://example.com/ | grep -i '^x-frame-options'
curl -sIL -A 'Mozilla/5.0' https://example.com/ \
| grep -i '^content-security-policy' | grep -o 'frame-ancestors[^;]*'
What this run cannot tell you: we did not test a single browser. Whether Chrome, Safari or Firefox resolves a contradiction the way the specification says is outside the data. We read what the servers claim, not what any client does with the claim.
16 of 27 still send X-Frame-Options
The header appears on 16 homepages with three distinct spellings: SAMEORIGIN nine times, DENY six times, and deny in lowercase once, on github.com. Not one site in the batch sent the third directive, ALLOW-FROM, which MDN describes as "an obsolete directive. Modern browsers that encounter response headers with this directive will ignore the header completely." (X-Frame-Options, read 2026-09-02.)
| Header | Sites | Share of 27 |
|---|---|---|
| X-Frame-Options only | 8 | 30% |
| frame-ancestors only | 4 | 15% |
| Both | 8 | 30% |
| Neither | 7 | 26% |
The eight running X-Frame-Options alone are nextjs.org, developer.mozilla.org, www.figma.com, www.framer.com, arstechnica.com, www.bbc.com, www.nytimes.com and slack.com. The four running only the CSP directive are linear.app, substack.com, www.notion.com and www.theverge.com. Seven declare no framing rule in either place: supabase.com, www.netlify.com, www.wired.com, www.wikipedia.org, astro.build, react.dev and about.gitlab.com.
Seventeen of the 27 send a Content-Security-Policy at all, so five of those seventeen ship a policy that says nothing about framing. Shipping a CSP and covering this particular case are separate decisions, and five teams made only the first one.
Eight sites send both, and five of them disagree
This is the part worth the measurement. W3C's Content Security Policy Level 2 is explicit about precedence: "The frame-ancestors directive obsoletes the X-Frame-Options header. If a resource has both policies, the frame-ancestors policy SHOULD be enforced and the X-Frame-Options policy SHOULD be ignored." (Content Security Policy Level 2, read 2026-09-02.) So when the two headers differ, one of them is decoration.
| Site | X-Frame-Options | frame-ancestors | Same rule? |
|---|---|---|---|
| github.com | deny | 'none' | yes |
| railway.com | SAMEORIGIN | 'self' | yes |
| techcrunch.com | SAMEORIGIN | 'self' | yes |
| www.cloudflare.com | SAMEORIGIN | 'none' | no — CSP is stricter |
| news.ycombinator.com | DENY | 'self' | no — CSP is looser |
| vercel.com | DENY | 'self' plus 3 hosts | no — CSP is looser |
| webflow.com | SAMEORIGIN | 'self' plus 3 hosts | no — CSP is looser |
| stripe.com | SAMEORIGIN | contentful plus 'self' | no — XFO cannot say this |
Four of the five disagreements point the same way: the CSP allows framing that the older header forbids. vercel.com sends DENY while its policy names its own app domain and two Contentful hosts. stripe.com allows app.contentful.com in the CSP, and there is no way to express that in X-Frame-Options at all — the allowlist directive that used to exist is the obsolete one nobody sends.
www.cloudflare.com runs the other way: SAMEORIGIN in the old header, 'none' in the new one. Read the specification and the answer is the stricter rule. Read the old header alone and you would expect your own pages to frame each other.
Two framing headers that disagree are not defence in depth. One of them is being ignored, and the header you read first is usually the one that lost.
What X-Frame-Options does not do
It does not affect crawling, indexing or citation. It is instruction to a browser about whether a document may be painted inside a frame, and a crawler fetching your HTML is not painting anything into a frame. Neither header appeared as a reason a page was unreachable in any check we have run.
That distinction is easy to lose because these headers travel in the same block as the ones that do change what a machine reader gets. Same batch, same day: x-content-type-options on 27 homepages found 15 of 27 sending nosniff, and HSTS across the same panel found 24 of 27 sending a policy. Only one header in that neighbourhood can leave a rendering engine with a blank page, and it is the one covered in content security policy and SEO.
So the honest framing is narrow. This survey measures tidiness, not reachability.
What this means for your site
Three checks, in order. The first takes one command.
- Read both headers on the same response. If only one exists, you are done — a single rule cannot contradict itself.
- If both exist, write down what each one permits and compare the two sentences. Five of eight sites in this sample would fail that comparison.
- When they differ, keep the CSP directive and delete the older header, or bring the older header in line. Leaving both in place means the next person to read your config learns the wrong rule.
There is one reason to keep both, and it is not the one usually given: very old clients understand X-Frame-Options and not frame-ancestors. That is an argument for keeping a matching pair, never for keeping a contradictory one. If you want to see what an engine actually receives from your pages, see how QueryWin reads a page.
Common questions
How did you measure this?
One GET per homepage on 2026-09-02, desktop Chrome user agent, redirects followed, headers of the final response recorded. X-Frame-Options was read verbatim; Content-Security-Policy was searched for frame-ancestors and the directive value stored. No JavaScript ran and no browser was involved. Exit node in Osaka, Japan.
Is X-Frame-Options deprecated?
The W3C calls frame-ancestors a replacement and says the older header should be ignored when both are present. Browsers still honour it when it stands alone, which is why 16 of 27 homepages in this batch still send it. Obsolete on paper, load-bearing in practice.
Which header wins when both are sent?
By specification, the CSP directive. We read that in Content Security Policy Level 2 on 2026-09-02 and did not verify it in any browser, so treat it as what the standard requires rather than as something we observed.
Does this header block AI crawlers?
No. It governs framing inside a browser. A crawler requesting your HTML never enters that code path, and nothing in this data set shows a page becoming harder to fetch because of it.
Why do sites keep sending both?
We cannot tell from headers alone. The pattern in the disagreements — old header strict, CSP permissive — is consistent with the CSP being added later by a different team, but that is a guess about org charts, and we have no evidence for it beyond the shape of the values.


