IndexNow 推送协议实战:一键提交 URL 同时通知 Bing/Yandex/Naver 等多家搜索引擎

很多站长做 SEO 都是 Bing、Yandex、Naver 一个平台一个平台地提交,其实有个协议可以一次提交、多家同步推送,这就是 IndexNow。本文从原理到部署,一步步讲清楚怎么用 PHP 脚本实现批量推送。

一、IndexNow 是什么,支持哪些搜索引擎

IndexNow 是一个开放的推送协议,你在网站上放一个密钥文件,然后通过 API 把新页面 URL 推送给 IndexNow,它会自动分发给所有支持该协议的搜索引擎,不用每个站长平台单独提交。

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

百度不支持 IndexNow,继续用百度自己的普通收录 API,两套并行不冲突。

二、和百度普通收录有什么区别

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

三、第一步:放密钥验证文件

1. 生成密钥

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

比如:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6

2. 创建 txt 文件

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

a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.txt

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

a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6

3. 验证文件能不能访问

浏览器打开:

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

必须满足:

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

几个容易踩的坑:

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

四、第二步:批量推送 PHP 脚本

新建一个 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. 修改配置区的域名、密钥、密钥文件地址。
  3. 把要推送的 URL 填进 $urlList 数组,单次不要超过 100 条。
  4. 浏览器访问 https://你的域名.com/push.php。

怎么看成功没有

看页面输出的响应头:

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

五、进阶:自动从数据库读 URL 批量推送

如果你的网站有数据库,可以让脚本自动读取最新文章 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 用户:发布文章自动推送

如果你用的是 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 是否拦截了海外请求。

3. 提交返回 400

  • JSON 格式错误(少括号、引号没闭合)。
  • urlList 为空。
  • URL 里带了多余的标记,要填纯 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 钩子,实现自动推送
  • 用完删除批量脚本
  • 百度继续用原来的推送方式,互不影响

发布日期:

所属分类: 网站运营 SEO 标签: