**最快的修复:**对出问题的 URL 跑 curl -sI https://yourdomain.com/path | grep -i x-robots。如果有 X-Robots-Tag: noindex 这个 header,就是它在压制你的 meta——Google 在两个信号里取最严格的值,所以 header 的 noindex 每次都胜过 meta 的 index。在注入它的那一层把这个多余的 header 去掉,再触发重抓。如果根本没有 header,直接跳到情况 5(robots.txt 把页面挡住了)。
你在 staging 页上加了 <meta name="robots" content="noindex">,一周后发现生产环境的同一页从 Google 消失了。或者反过来:你在感谢页 meta 里写了 noindex,但它还在搜索结果里。两种情况的根源都是同一个——Google 通过两条通道读取 robots 指令,两条不必一致。HTTP 响应头 X-Robots-Tag 是另一条通道;当两者不一致时,Google 不会选一个作权威。正如 Google 的 robots meta tag 规范所写:“In the case of conflicting robots rules, the more restrictive rule applies.”(冲突时取更严格的规则)。也就是说它合并两条通道,逐项取最严格的值。
换句话说,CDN 规则里一条不起眼的 X-Robots-Tag: noindex、一个过期的 Vercel 部署、或者一段源站中间件,都可以静默杀掉一个 meta 里写着 index 的 HTML 页面。View Source 看不出问题——浏览器不给你看响应头。只有 curl -I(或 Network 面板,或 Search Console 的”HTTP 响应”视图)能看到真相。
先判断你属于哪一类
先跑下面两条检查,再对照命中的那一行:
Meta(curl -s + grep robots) | Header(curl -sI + grep x-robots) | robots.txt | 你的情况 |
|---|---|---|---|
noindex | 无 | 允许 | 情况 1——还没重抓,或 meta 是 JS 设的 |
index / 无 | noindex | 允许 | 情况 2——某个 header 在泄漏 noindex |
| 不适用(PDF、图片、ZIP) | noindex | 允许 | 情况 3——非 HTML 资源被全局加了 header |
| 每次抓取都在变 | 每次抓取都在变 | 允许 | 情况 4——JS 在加载后改了 meta |
noindex | noindex | Disallow | 情况 5——robots.txt 把抓取整个挡住了 |
最后一列告诉你该用哪种修复。绝大多数”我设了 noindex 却没生效”(或”我没设 noindex,页面却消失了”)的反馈都落在情况 2 和情况 5。
先判断你属于哪种情况
情况 1:meta 里有 noindex,但页面仍被收录
怎么发现:
curl -s https://yourdomain.com/path | grep -i 'name="robots"'
# 输出:<meta name="robots" content="noindex">
curl -sI https://yourdomain.com/path | grep -i x-robots
# 输出:(什么都没有)—— meta 说 noindex,header 什么也没说
然后 Search Console 的 URL 检查里这一页显示已被收录。
原因:自从你加 meta 之后 Google 还没有重新抓取,或者 meta 是用 JavaScript 渲染的、本次抓取里 Googlebot 没执行 JS。header 是每次请求都会读到的;meta 要等重抓 + 渲染才能生效。
修复:把 noindex 渲染进 SSR 的初始 HTML(不要靠客户端 JS),然后用 URL 检查里的”测试实际网址”确认 Google 在渲染 HTML 里看到了 noindex,再点”申请编入索引”触发重抓。完整移除时间线见 设了 noindex 但页面还在搜索结果里。
情况 2:meta 没有 noindex,但页面却从索引消失
怎么发现:
curl -sI https://yourdomain.com/path | grep -i x-robots
# X-Robots-Tag: noindex, nofollow
浏览器打开页面、查看源代码——没有 robots meta,或者写的是 index, follow。罪魁就是这个 header。
原因:典型泄漏路径:
- 过期的 Vercel 部署。Vercel 会自动给系统生成的
*.vercel.appURL,以及没有绑定到 Production Domain 的部署——包括你推新版本后那些过期的生产部署——发送X-Robots-Tag: noindex(见 Vercel 关于预览是否被收录的 KB)。如果 Google 之前收录过某个裸部署 URL,现在它读到的就是noindex。绑定到非生产分支的自定义域不会带这个 header,所以这个坑通常是某个裸*.vercel.appURL 漏进了索引。 - **host 模式过度匹配。**WAF 或 CDN 规则原本只想覆盖
*.staging.example.com,但 host 模式同时匹配到了你的主域名。 - **生产没设 env 变量。**源站中间件根据
NODE_ENV !== "production"加上X-Robots-Tag: noindex,结果生产环境其实没设NODE_ENV,这个判断永远为真,规则照样生效。
修复:定位哪一层注入了 header。一层一层往回找:
# 直连源站(绕过 CDN)
curl -sI --resolve yourdomain.com:443:ORIGIN_IP https://yourdomain.com/path | grep -i x-robots
# 再走 CDN
curl -sI https://yourdomain.com/path | grep -i x-robots
源站干净、CDN 脏 → CDN 规则;两者都脏 → 源站/应用层。
情况 3:PDF、图片或其他非 HTML 资源从搜索消失
怎么发现:
curl -sI https://yourdomain.com/whitepaper.pdf | grep -i x-robots
PDF、图片、其他非 HTML 响应无法承载 <meta> 标签。对它们而言,Google 唯一能读到的 robots 信号就是 X-Robots-Tag。如果托管平台或框架把 X-Robots-Tag: noindex 作为静态资源的默认值,你的 PDF 永远无法被收录。
原因:某些框架(Next.js 的默认 header、S3+CloudFront 配了默认 noindex 策略)会给所有响应、包括静态资源都加 X-Robots-Tag。
修复:把 noindex 规则限定到 HTML 页面或具体路径,而不是全站默认。
情况 4:表现飘忽——有时被收录有时没被
怎么发现:URL 检查显示渲染后的 HTML 带 noindex,但原始响应(“HTTP 响应”那一栏)没有。或者反过来。
原因:JavaScript 在页面加载后修改 meta。本次抓取 Googlebot 执行了 JS 就看到 noindex;没执行就看到原始的 index 值。header 通道始终被读取;meta 通道依赖渲染。
修复:不要用客户端 JS 切换 robots meta。在 SSR HTML 里就把最终值渲染出来,或者用服务端的 X-Robots-Tag。
情况 5:两边都写了 noindex,页面还在被收录
怎么发现:
# 两个信号都在
curl -s https://yourdomain.com/path | grep -i robots # meta 写了 noindex
curl -sI https://yourdomain.com/path | grep -i x-robots # X-Robots-Tag: noindex
# 但是:
curl -s https://yourdomain.com/robots.txt | grep -i path
# Disallow: /path
原因:robots.txt Disallow 把抓取整个挡住了。Google 永远不去取这一页,永远看不到 meta 或 header,仅凭外链信号继续把 URL 留在索引里(就是那个著名的”虽被 robots.txt 屏蔽,但仍被收录”状态)。这是 noindex 失败最常见的形态。
修复:删掉 Disallow 那一行。URL 必须可抓取,Google 才能看到 noindex 并完成移除。
Google 怎么解决冲突
按 Google 文档(robots meta tag 规范):
- 凡是能写进 robots meta 的规则,都能用
X-Robots-Tagheader 发送——它们是同一套词汇、两条通道,都是有效信号。 - 两条通道同时存在时,“the more restrictive rule applies”(取更严格的规则)——按指令逐项判断,而不是按来源整体取舍。
noindex胜index,nofollow胜follow。摘要类控制里,nosnippet胜过任何max-snippet:[number],更小的max-snippet胜过更大的。- 如果
robots.txt屏蔽了 URL,两个信号都读不到:“any information about indexing or serving rules will not be found and will therefore be ignored.”(关于索引或展示的规则都不会被发现,因此被忽略)。URL 还可能以无摘要的形式留在结果里。
一条过时建议要纠正:noarchive 和 nocache 已不再是受支持的索引规则——别再用了。所以就有意义的规则而言,meta 和 header 之间不存在”谁赢”,是合并。实操原则:生产环境里绝不让它们打架。(完整指令清单和原文措辞见 Google 的 robots meta tag 规范。)
最短修复路径
按命中率排序:
- 对问题 URL 跑
curl -I→ 60% 的情况下 header 就是凶手。View Source 里的 meta 会让你忽视真正原因。 - 看
robots.txt→ 25% 的情况下是Disallow让 Google 永远看不到你设的信号。 - 逐层排查请求链路 → 源站 header 正确但边缘错了,就是 CDN / WAF / 托管平台的规则。
- 把 robots meta 写到 SSR,别靠 JS → 剩下的边缘情况几乎都是”JS 设了 meta 但 Googlebot 这次没跑 JS”。
一个安全的生产配置
按内容类型分工。下面这套覆盖绝大多数站:
- HTML 页面:robots meta 写进 SSR HTML。HTML 响应不要再加
X-Robots-Tag,除非有特殊理由。 - PDF、图片、下载文件:用
X-Robots-Tagheader(meta 用不了)。 - Staging 域名:
X-Robots-Tag: noindex严格限定在 staging 主机名上。
示例:把 staging 的 noindex 限定到主机名,而不是全局。
# Nginx——只在 staging
server {
server_name staging.yourdomain.com;
add_header X-Robots-Tag "noindex, nofollow" always;
}
server {
server_name yourdomain.com;
# 这里不加 X-Robots-Tag。每页的 noindex 走 meta。
}
怎么确认已经修好
别信 View Source——要在 header 层和 Google 自己的视图里确认:
curl -sI https://yourdomain.com/path | grep -i x-robots返回空(或你期望的值)。CDN URL 和源站都要各跑一遍,因为边缘可能会改写 header。- 在 Search Console 里对该 URL 跑 URL 检查 → 点 测试实际网址。展开 HTTP 响应 一栏,确认没有意外的
x-robots-tag。“是否允许编入索引?“那一行应显示 是。 - 点 申请编入索引 排队一次新抓取。注意配额:截至 2026 年 6 月,Search Console 每个资源每天大约只允许 10–12 次手动提交,一旦用满,按钮会灰掉 24 小时。少数几个重要页面这样做没问题;要做全站修复,就靠正常抓取周期,并重新提交 sitemap。
- 等重抓。首页或高流量页通常 24–72 小时内重新收录;深层、低流量的页面可能要一周以上。
预防建议
- 按文件类型记录哪个信号 canonical,写进仓库里的 SEO README。
- CI 加一条检查:对生产 URL 抽样跑
curl -I,意外出现X-Robots-Tag就让构建失败。 - 同一 URL 绝不同时 meta
noindex+robots.txt Disallow——Google 永远看不到 noindex。 - 不要用客户端 JS 切换 robots meta——Googlebot 本次可能跳过 JS。
- 改完 Vercel / Netlify / Cloudflare 设置后,立刻对若干页面跑
curl -I验证 header 没有意外变化。
FAQ
Q:meta 里设了 noindex 但页面还在 Google。先查什么?
A:先跑 curl -sI https://yourdomain.com/path | grep -i x-robots。如果没 header,再看 robots.txt 是不是对这个路径写了 Disallow。这两步能解决约 85% 的情况。都不是的话,几乎都是”Google 还没重抓”——等,或者用 URL 检查里的”申请编入索引”。
Q:同一页能同时用 meta 和 X-Robots-Tag 吗?
A:能,但必须一致。Google 按最严格的指令合并。meta 写 index、header 写 noindex,最终结果是 noindex。HTML 上同时写两个是冗余,选一个就好。
Q:X-Robots-Tag 能用在 HTML 上吗?
A:能,效果和 meta 完全一致。只是不那么常见,因为大多数 CMS 会替你写 meta。X-Robots-Tag 是非 HTML(PDF、图片、ZIP)等无处写 meta 的场景的正确选择。
Q:staging 把 noindex 泄漏到了生产,怎么最快撤销?
A:先把 header 移掉(部署或改 CDN 规则),再去 Search Console:对受影响 URL 做 URL 检查 → “测试实际网址” → 在 HTTP 响应视图里确认 header 已消失 → “申请编入索引”。首页或顶层页通常 24–72 小时就能重新收录。记得每天约 10–12 次提交的上限,优先提交最重要的 URL。
Q:我站点的某个 something.vercel.app URL 在 Google 里,但真正的域名却不在,为什么?
A:Vercel 默认会给系统生成的 *.vercel.app URL 加 X-Robots-Tag: noindex,所以这些本不该被收录——但如果 Google 在读到 header 之前就通过某个链接发现了它,那个裸 URL 可能会残留。修法是把 canonical 和站内链接都指向你的生产域名,确认生产域名不返回 noindex header(curl -sI),再让那个 *.vercel.app URL 自然掉出索引。永远不要把裸部署 URL 当作 canonical 来对外提供真实内容。
Q:nosnippet、max-snippet 在 meta 和 header 之间的合并规则一样吗?
A:一样——同样取最严格的值。meta 写 max-snippet:50、header 写 max-snippet:200,最终生效的是 50。而 nosnippet 会盖过任意一条通道上的任何 max-snippet 值。