一次提交 URL,同时通知 Bing、Yandex、Naver 等多家海外搜索引擎来抓取,不用每个平台单独提交。 百度不支持 IndexNow,继续用百度自己的普通收录 API,两者并行不冲突。


一、IndexNow 是什么

IndexNow 是一个搜索引擎推送协议,你在网站上放一个密钥文件,然后通过 API 把新页面 URL 推送给 IndexNow,它会分发给所有支持该协议的搜索引擎。

支持的搜索引擎

搜索引擎 国家/地区 支持情况
Bing(必应) 全球 ✅ 完全支持
Yandex 俄罗斯 ✅ 完全支持
Naver 韩国 ✅ 支持
Seznam 捷克 ✅ 支持
Yep 全球(隐私搜索引擎) ✅ 支持
Mojek 波兰 ✅ 支持
百度 中国大陆 ❌ 不支持

工作原理

  1. 在网站根目录放一个密钥验证文件。
  2. 通过 API POST 提交 URL 列表,带上密钥。
  3. 搜索引擎后端访问你的密钥文件验证所有权。
  4. 验证通过后,搜索引擎安排爬虫来抓取页面。

二、和百度推送的区别

对比项 百度普通收录 IndexNow
推送对象 百度 Bing / Yandex / Naver 等
接口地址 data.zz.baidu.com api.indexnow.org/indexnow
推送方式 POST text/plain POST application/json
所有权验证 不需要,用 token 需要在根目录放密钥文件
单次 URL 数 每日有额度 单次最多 100 条
限制 每日额度 频率过高返回 429

三、密钥文件准备(关键步骤)

1. 生成密钥

去 https://www.indexnow.org/ 自动生成一个随机密钥,或者自己写一段 8~128 位的随机字符串(只允许大小写字母、数字、横线)。

示例:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6

2. 创建密钥文件

在网站根目录新建一个 txt 文件,文件名就是密钥,例如:

a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.txt

文件内容只写密钥本身,不要多空格、换行、回车:

a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6

3. 验证密钥文件

浏览器访问:

https://你的域名/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.txt

必须满足:

  • ✅ 裸文本直接显示密钥
  • ✅ HTTP 状态码 200
  • ✅ 不能 404 / 403 / 301 跳转
  • ✅ 海外 IP 也能访问(国内能打开 ≠ 海外 Bing 爬虫能打开)

常见坑

  • 密钥区分大小写,文件名大小写错一个字符就失败。
  • 文件编码必须 UTF-8 无 BOM。
  • 文件内容不能有多余的换行和空格。
  • 国内服务器如果有 WAF / 云锁 / 安全组拦截了海外 IP,搜索引擎后端访问不到这个 txt,会返回 403。

四、批量推送脚本(通用版)

新建一个 PHP 文件,放到网站根目录,例如 push.php:

<?php
// ===== 配置区,改成你自己的 =====
$host = "你的域名.com";
$key  = "你的密钥";
$keyLocation = "https://你的域名.com/你的密钥.txt";

// 要推送的 URL 列表,单次最多 100 条
$urlList = [
    "https://你的域名.com/post-1.html",
    "https://你的域名.com/post-2.html",
    "https://你的域名.com/post-3.html",
    // 继续添加,不要超过 100 条
];

// ===== 以下代码不用改 =====
$postData = json_encode([
    "host"        => $host,
    "key"         => $key,
    "keyLocation" => $keyLocation,
    "urlList"     => $urlList,
], JSON_UNESCAPED_SLASHES);

$opts = [
    'http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/json; charset=utf-8\r\n",
        'content' => $postData,
        'timeout' => 30,
    ],
];
$context = stream_context_create($opts);
$result = file_get_contents('https://api.indexnow.org/indexnow', false, $context);
$responseHeaders = $http_response_header;

echo "推送数量:" . count($urlList) . " 条<br>";
echo "返回内容:" . var_export($result, true) . "<br>";
echo "<pre>响应头:";
print_r($responseHeaders);
echo "</pre>";
?>

使用方法

  1. 把上面代码保存为 push.php,上传到网站根目录。
  2. 修改配置区的 $host、$key、$keyLocation。
  3. 把要推送的 URL 填入 $urlList 数组,单次不要超过 100 条。
  4. 浏览器访问 https://你的域名.com/push.php。

判断是否成功

看响应头里的状态码:

  • HTTP 200 OK + Content-Length: 0 = ✅ 提交成功,响应体为空是正常现象。
  • 如果看到 X-MSEdge-Ref 开头的响应头,说明请求已经到了微软 Bing 的服务器。

五、自动从数据库读 URL 批量推送(适合 BBS / CMS)

如果你的网站有数据库,可以让脚本自动读取最新文章 URL,不用手动复制粘贴。

以 SQLite 数据库为例:

<?php
$host = "你的域名.com";
$key  = "你的密钥";
$keyLocation = "https://你的域名.com/你的密钥.txt";

// 连接数据库,读取最新文章
$dbFile = __DIR__ . '/site.db';
$db = new PDO("sqlite:{$dbFile}");
$stmt = $db->query("SELECT id FROM article ORDER BY create_time DESC LIMIT 100");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

$urls = [];
foreach ($rows as $r) {
    $urls[] = "https://你的域名.com/article-{$r['id']}.html";
}

// 推送
$postData = json_encode([
    "host"        => $host,
    "key"         => $key,
    "keyLocation" => $keyLocation,
    "urlList"     => $urls,
], JSON_UNESCAPED_SLASHES);

$opts = [
    'http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/json; charset=utf-8\r\n",
        'content' => $postData,
        'timeout' => 30,
    ],
];
$context = stream_context_create($opts);
$result = file_get_contents('https://api.indexnow.org/indexnow', false, $context);

echo "推送数量:" . count($urls) . " 条<br>";
echo "返回结果:" . $result;
?>

MySQL 数据库的话,把 PDO 连接串改成 MySQL 的即可,SQL 查询语句对应修改。


六、WordPress 自动推送(functions.php 钩子)

如果你用的是 WordPress,可以把下面代码加到当前主题的 functions.php,实现发布 / 更新文章时自动推送,以后新增文章不用手动跑脚本:

// IndexNow 自动提交
add_action('save_post', function ($post_id) {
    if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) return;
    if (get_post_type($post_id) !== 'post') return;
    if (get_post_status($post_id) !== 'publish') return;

    $url = get_permalink($post_id);
    $host = "你的域名.com";
    $key  = "你的密钥";
    $keyLocation = "https://你的域名.com/你的密钥.txt";

    $postData = json_encode([
        "host"        => $host,
        "key"         => $key,
        "keyLocation" => $keyLocation,
        "urlList"     => [$url],
    ], JSON_UNESCAPED_SLASHES);

    $opts = [
        'http' => [
            'method'  => 'POST',
            'header'  => "Content-Type: application/json; charset=utf-8\r\n",
            'content' => $postData,
            'timeout' => 15,
        ],
    ];
    $context = stream_context_create($opts);
    @file_get_contents('https://api.indexnow.org/indexnow', false, $context);
}, 10, 1);

注意:这个钩子只管新增 / 更新文章,存量历史文章仍然需要用第四节的批量脚本一次性推送。


七、接口返回码说明

HTTP 状态码 含义 排查方向
200 OK ✅ 提交成功 响应体为空是正常的
400 Bad Request ❌ 请求格式错误 JSON 格式不对、URL 非法
403 Forbidden ❌ 密钥校验失败 搜索引擎访问不到你的 txt 文件,或文件内容不对
422 Unprocessable Entity ❌ URL 域名不匹配 urlList 里的域名和 host 字段不一致
429 Too Many Requests ❌ 请求过多 频率太高,隔几分钟再试

八、常见问题排查

1. 访问密钥 txt 返回 404

  • 检查文件名是否和密钥完全一致(大小写敏感)。
  • 检查文件是否在网站根目录。
  • 检查 Nginx / Apache 伪静态规则是否拦截了 .txt 文件。

2. 提交返回 403

  • 国内浏览器能打开 txt,但海外 Bing 爬虫打不开。
  • 检查服务器防火墙 / 安全组是否限制了海外 IP。
  • 检查 CDN / WAF 是否拦截了海外请求。
  • 用海外代理访问你的 txt,确认海外可访问。

3. 提交返回 400

  • JSON 格式错误(少括号、引号没闭合)。
  • urlList 为空。
  • URL 里带了 markdown 链接标记,要填纯 URL。

4. PHP 脚本访问报 500

  • 检查 php.ini 的 allow_url_fopen 是否开启(必须 On)。
  • 检查 disable_functions 是否禁用了 file_get_contents。
  • 看 PHP 错误日志定位。

5. 脚本返回空、没有响应头

  • 服务器出站网络无法访问 api.indexnow.org,国内服务器常见。
  • 可以尝试用 CDN / 海外中转服务器跑脚本。

九、注意事项

  1. 单次最多提交 100 条 URL,超过就分批。
  2. 不要反复推送未修改的旧 URL,不会加速收录,反而可能被判定为垃圾提交。
  3. 批量推送脚本用完就删,不要长期留在公网,防止别人恶意调用触发 429 限流。
  4. 如果必须保留脚本,加访问密码,只允许自己访问。
  5. IndexNow 只推海外搜索引擎,百度继续用自己的普通收录 API,两套并行。
  6. 提交成功只是通知搜索引擎来抓取,不等于立刻收录,收录还要看页面质量和网站权重。

十、快速上手清单

  • [ ] 生成密钥,根目录放 {密钥}.txt 文件
  • [ ] 浏览器访问 txt 文件,确认返回 200、裸文本显示密钥
  • [ ] (可选)确认海外 IP 也能访问这个 txt
  • [ ] 复制第四节的批量脚本,改成自己的域名和密钥
  • [ ] 填入要推送的 URL(≤100 条),访问脚本提交
  • [ ] 看返回 200 即成功
  • [ ] (可选)WordPress 用户加第六节的 functions.php 钩子,实现自动推送
  • [ ] 用完删除批量脚本
  • [ ] 百度继续用原来的推送方式,互不影响