27 个首页的 x-frame-options:16 个还在发,8 个同时发两个头、5 个自相矛盾

x-frame-options 在 2026-09-02 读到的 27 个首页里出现了 16 次,同一批站有 12 个发了 CSP 的 frame-ancestors。两个都发的 8 个站里,5 个的两个头说的不是同一件事 —— 而这个头和抓取、收录没有关系。

抓取与收录5 分钟读完2753 次阅读
27 个首页的 x-frame-options:16 个还在发,8 个同时发两个头、5 个自相矛盾

实测 · 2026-09-02 · 27 个首页 · 各请求一次 · X-Frame-Options 与 CSP frame-ancestors

样本 / 口径:30 个站在 2026-09-02 各发一次 GET,桌面 Chrome UA(不是 Googlebot),跟随跳转,不执行 JavaScript。剔掉 3 个 —— stackoverflow.com 与 medium.com 返回 403,www.reddit.com 只回了一个 8,393 字节的空壳 —— 纳入 27 个。只读跟随跳转后最终那一次响应的头。

先把最容易混的一件事切开:x-frame-options 管的是浏览器允不允许把你的页面套进 iframe,跟抓取和收录没有一点关系。2026-09-02 这天读到的 27 个首页里,16 个还在发这个头,12 个发了 CSP 里的 frame-ancestors(W3C 说它取代前者),两个都发的有 8 个 —— 而这 8 个里有 5 个,两个头说的不是同一件事。

怎么测的

每站一次 GET,桌面 Chrome UA 而不是 Googlebot,跟随跳转,不重试。下面每个数字都来自最终那次响应的头,全程不渲染,也没有开过任何一个浏览器。本机出口在日本大阪 —— 有些站会按地区发不同的头,这一条得写在前面。

读两个字段:X-Frame-Options 原样记下;Content-Security-Policy 里搜 frame-ancestors 这个子串,取到就把指令值存下来。发成 Content-Security-Policy-Report-Only 的单独数,本批只有 1 个站发了,而且里面没有嵌入相关的指令,所以它不影响任何一个数字。

# 在自己的站上读同样两个头
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[^;]*'

这次没测的东西也得摆在前面:一个浏览器都没开过。Chrome、Safari、Firefox 遇到两个头打架时是不是真按规范办,不在这份数据里。我们读到的是服务器怎么声明,不是客户端怎么执行。

16 个站还在发 x-frame-options,其中一个是小写

这个头在 16 个首页上出现,写法有三种:SAMEORIGIN 九次、DENY 六次,还有一次是小写的 deny,来自 github.com。第三个指令 ALLOW-FROM 一个站都没发 —— MDN 对它的说法是:「This is an obsolete directive. Modern browsers that encounter response headers with this directive will ignore the header completely.」(X-Frame-Options,2026-09-02 访问。)

情况站数占比
只发 X-Frame-Options830%
只发 frame-ancestors415%
两个都发830%
两个都不发726%

只发老头的八个是 nextjs.org、developer.mozilla.org、www.figma.com、www.framer.com、arstechnica.com、www.bbc.com、www.nytimes.com、slack.com。只发 CSP 指令的四个是 linear.app、substack.com、www.notion.com、www.theverge.com。两处都没声明嵌入规则的七个是 supabase.com、www.netlify.com、www.wired.com、www.wikipedia.org、astro.build、react.dev、about.gitlab.com。

再往下拆一层:27 个里有 17 个发了 Content-Security-Policy,也就是说这 17 个里有 5 个的策略压根没提嵌入这件事。发不发 CSP、要不要在里面管嵌入,是两个决定,有 5 家只做了前一个。

两个头都发的 8 个站里,5 个自相矛盾

这一节才是这次测量的价值所在。W3C 的 Content Security Policy Level 2 把优先级写死了:「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,2026-09-02 访问。)所以两个头不一样的时候,其中一个是摆设。

站点X-Frame-Optionsframe-ancestors一致吗
github.comdeny'none'一致
railway.comSAMEORIGIN'self'一致
techcrunch.comSAMEORIGIN'self'一致
www.cloudflare.comSAMEORIGIN'none'否,CSP 更严
news.ycombinator.comDENY'self'否,CSP 更宽
vercel.comDENY'self' 加 3 个域否,CSP 更宽
webflow.comSAMEORIGIN'self' 加 3 个域否,CSP 更宽
stripe.comSAMEORIGINcontentful 加 'self'否,老头写不出

五处不一致里有四处是同一个方向:CSP 放开了老头明确禁掉的嵌入。vercel.com 发的是 DENY,策略里却点名了自家 app 域和两个 Contentful 域。stripe.com 在 CSP 里放行 app.contentful.com,而这件事用 X-Frame-Options 根本表达不了 —— 能写白名单的那个指令,正是没人发的那个废弃指令。

www.cloudflare.com 是反过来的:老头写 SAMEORIGIN,新头写 'none'。按规范作数的是更严的那条。只看老头,你会以为自家页面之间可以互相嵌。

两个互相打架的 framing 头不叫双保险。其中一个正在被忽略,而先被读到的那个,往往就是输掉的那个。

它不影响抓取,也不影响收录

这个头是给浏览器的:这份文档能不能被画进一个 frame。爬虫拉走你的 HTML 时没有画任何 frame,所以它既不改变抓取,也不改变收录,更不会决定你被不被引用。它不管抓取。

之所以容易混,是因为它和真正会影响机器读取的那些头挤在同一段响应里。同一批站、同一天:x-content-type-options 的 27 个首页实测 数到 15 个站发 nosniff同一批站的 strict-transport-security 数到 24 个。这一片里真正能让渲染器拿到空页面的只有一个头,它的成因和修法在 content-security-policy 挡住你自己的页面 里。

所以这篇的口径要说窄:它量的是整洁度,不是可达性。

这对你的站意味着什么

三步,按顺序做。第一步一条命令就够。

  1. 在同一次响应上把两个头一起读出来。只有一个的话到此为止 —— 一条规则不会跟自己打架。
  2. 两个都有,就把各自允许的范围写成两句话摆在一起比。本批 8 个站里有 5 个过不了这一比。
  3. 不一致的话,留下 CSP 指令、删掉老头,或者把老头改成一致。两个都留着,下一个来读配置的人学到的就是错的那条规则。

确实有一个理由值得两个都留,但不是常被说的那个:很老的客户端认 X-Frame-Options、不认 frame-ancestors。这只支持保留一对写法相同的头,从来不支持保留一对互相矛盾的。想看引擎从你自己的页面上实际拿到什么,可以 看看 QueryWin 怎么读一个页面

常见问题

你们是怎么测的?

2026-09-02 每个首页发一次 GET,桌面 Chrome UA,跟随跳转,记录最终响应的头。X-Frame-Options 原样读,Content-Security-Policy 里搜 frame-ancestors 并存下指令值。不执行 JavaScript,不开浏览器。出口在日本大阪。

x-frame-options 是不是已经废弃了?

W3C 把 frame-ancestors 称作它的替代品,并要求两个同时存在时忽略老的那个。但老头单独存在时浏览器照样认,这也是 27 个首页里还有 16 个在发它的原因。纸面上过时,实际上还在承重。

两个头同时发,哪个作数?

按规范是 CSP 那个。这句话我们是 2026-09-02 从 Content Security Policy Level 2 里读到的,没有在任何浏览器里验过 —— 请当成标准的要求,不是我们观测到的行为。

这个头会挡住 AI 爬虫吗?

不会。它管的是浏览器里的嵌入行为。爬虫请求你的 HTML 时压根走不到那条代码路径,这份数据里也没有任何一页因为它而变得更难取。

为什么很多站两个都发?

光看响应头判断不了。不一致的那五处形状一致 —— 老头严、CSP 宽 —— 和「CSP 是后来另一拨人加的」这种解释对得上,但那是在猜组织结构,除了取值的形状我们没有任何证据。

27 个首页的 x-frame-options:16 个还在发,8 个同时发两个头、5 个自相矛盾