IndexNow — открытый протокол, который позволяет сайту самостоятельно сообщать поисковикам о новом или изменённом URL, не дожидаясь следующего обхода. Поддерживают его Microsoft Bing, Яндекс и десяток других поисковых систем, использующих общий пул отправленных URL. В обычном режиме страница попадает в индекс через несколько часов или дней; с IndexNow временной разрыв сокращается до минут. В этом руководстве разбираемся, зачем нужен IndexNow, чем он отличается от классического sitemap-пинга, как реализовать отправку запроса вручную через curl, как этот процесс автоматизирует Crawler и какие подводные камни встречаются на практике.

Гайд написан для разработчиков и SEO-специалистов, которым нужно ускорить переиндексацию динамических сайтов: новостных лент, e-commerce-каталогов, блогов с частыми правками, документации, баз знаний. Если вы поддерживаете сайт, который обновляется чаще одного раза в сутки, IndexNow закрывает реальную боль; для статичных проектов разница менее заметна, но реализация всё равно недорогая.

Sitemap-пинг и IndexNow: в чём разница

До 2021 года основным способом «постучать» в поисковик после публикации страницы был sitemap-пинг — отправка GET-запроса на специальный URL вида https://www.google.com/ping?sitemap=… или его аналог в Яндексе. По факту это сообщало поисковику: «обнови у себя кэш моего sitemap.xml». Подход работал, но имел три неустранимых недостатка.

Во-первых, sitemap-пинг указывает на весь файл, а не на конкретный URL. Поисковик должен повторно скачать карту сайта, сравнить даты <lastmod> у тысяч записей и решить, какие URL переобходить. Если sitemap большой, эта работа откладывается в очередь, и обновлённая статья может всплыть на обход через сутки.

Во-вторых, sitemap-пинг не передаёт намерения «эта страница изменилась прямо сейчас». Поисковик никак не знает, что обновился именно /blog/post-42, а не /about. Решение об обходе принимает планировщик, опираясь на свои внутренние сигналы и приоритеты домена. Низкоавторитетные сайты в очереди оказываются глубоко.

В-третьих, Google в июне 2023 года официально отключил sitemap-пинг: запросы по адресу /ping?sitemap=… возвращают код 200, но игнорируются. Яндекс и Bing всё ещё поддерживают этот вызов, но сами активно продвигают IndexNow вместо него.

IndexNow устроен принципиально иначе. Это POST-запрос с JSON-телом, содержащим список из 1–10 000 URL и идентификатор сайта (ключ). Поисковик получает явный сигнал: «вот эти конкретные адреса либо появились, либо изменились — переобойти как можно скорее». Никакого парсинга sitemap, никакого ожидания планировщика; URL попадают в краулинговую очередь немедленно. Главные различия удобно держать в голове так:

  • Гранулярность. Sitemap-пинг говорит про файл целиком, IndexNow — про конкретные адреса.
  • Скорость. Sitemap уходит в очередь обработки sitemap, IndexNow — в краулинговую очередь напрямую.
  • Распространение. Один IndexNow-запрос обрабатывают все участники протокола (Bing, Yandex, Seznam и др.) — достаточно отправить его одному эндпоинту, остальные подхватят URL из общего пула.
  • Поддержка Google. Google пока официально не присоединился, но и sitemap-пинг он больше не обрабатывает. Это означает, что IndexNow не покрывает Google напрямую — но не покрывает его и sitemap-пинг.
  • Лимиты. Sitemap — 50 000 URL в одном файле; IndexNow — 10 000 URL в одном запросе и неограниченное число запросов в сутки (при разумном поведении).

Практический вывод: IndexNow — это не замена sitemap.xml. Sitemap по-прежнему нужен как «карта» сайта для первичного обхода, а IndexNow — оперативный канал уведомлений о точечных изменениях. Связка работает хорошо: краулер находит новые разделы через sitemap, а правки и срочные публикации забирает через IndexNow.

Как отправить IndexNow-запрос руками

Минимальная реализация занимает пять шагов. Все шаги обязательны: пропуск любого приводит к ошибке валидации на стороне Bing/Яндекса и URL не попадает в индекс.

Шаг 1. Сгенерировать ключ

Ключ — это случайная строка из латиницы и цифр длиной от 8 до 128 символов. Подойдёт любой UUID без дефисов или результат openssl rand -hex 16. Главное — больше нигде его не использовать; ключ работает как «подпись» сайта, а не как настоящий секрет, но утечка позволит злоумышленнику пинговать чужие URL от вашего имени.

Шаг 2. Опубликовать ключ-файл

В корне сайта должен быть доступен файл https://example.com/<KEY>.txt, содержащий ровно одну строку — сам ключ. Это требование стандарта: оно подтверждает, что отправитель действительно владеет доменом. Если файл недоступен или возвращает не тот ключ — поисковик отвергнет любой POST-запрос.

# https://example.com/abc123def4567890.txt
abc123def4567890

Файл должен возвращать Content-Type: text/plain и HTTP 200. Не закрывайте его robots.txt или авторизацией — поисковик ходит за ним без cookies.

Шаг 3. Сформировать payload

Тело запроса — JSON с четырьмя полями:

{
  "host": "example.com",
  "key": "abc123def4567890",
  "keyLocation": "https://example.com/abc123def4567890.txt",
  "urlList": [
    "https://example.com/blog/post-42",
    "https://example.com/blog/post-43"
  ]
}
  • host — голый домен без схемы и слэшей.
  • key — тот самый ключ.
  • keyLocation — необязательное поле, но рекомендуется указать. Без него ключ-файл должен лежать строго в корне; с ним можно держать файл по любому пути в пределах домена.
  • urlList — массив абсолютных URL, от 1 до 10 000 элементов. Все URL обязаны принадлежать домену из host и быть в правильном протоколе (http или https — тот же, что в host-файле).

Шаг 4. Отправить POST

Эндпоинт Bing — https://www.bing.com/indexnow, эндпоинт Яндекса — https://yandex.com/indexnow. Достаточно отправить запрос одному из них: внутри протокола URL расходятся по всем участникам. Базовый curl-пример:

curl -X POST 'https://www.bing.com/indexnow' \
  -H 'Content-Type: application/json; charset=utf-8' \
  --data '{
    "host": "example.com",
    "key": "abc123def4567890",
    "keyLocation": "https://example.com/abc123def4567890.txt",
    "urlList": [
      "https://example.com/blog/post-42",
      "https://example.com/blog/post-43"
    ]
  }'

Возможные ответы:

  • 200 OK — URL приняты в обработку. Это не гарантия немедленной индексации, но сигнал о том, что запрос прошёл валидацию.
  • 202 Accepted — то же самое, но с пометкой, что обработка отложена (например, при превышении частоты).
  • 400 Bad Request — невалидный JSON, неверный host, URL за пределами домена или больше 10 000 элементов.
  • 403 Forbidden — ключ-файл недоступен или содержит неверный ключ.
  • 422 Unprocessable Entity — формально правильный JSON, но ошибки в данных (например, URL с http при host-файле на https).
  • 429 Too Many Requests — слишком много пингов с домена за короткое время.

Шаг 5. Логировать результат

Без логирования ошибки незаметны: URL ушёл, но в индекс не попал, а узнаешь об этом через две недели в Search Console. Минимум — писать в свой лог код ответа, время и список URL. Лучше — складывать в БД, чтобы можно было разобрать выборку «какие пинги были по этой странице за последний месяц». Именно так устроена таблица ping_log в Crawler.

Как Crawler автоматически управляет IndexNow

Делать IndexNow руками на каждое обновление контента — путь к человеческим ошибкам: забыли отправить, отправили дубль, послали URL чужого домена. Crawler автоматизирует весь цикл, чтобы пользователю не приходилось трогать ни один из пяти шагов. Логика реализована вокруг трёх событий и одного «догоняющего» процесса.

Событие 1. Изменение контента (SimHash diff)

На каждом плановом кроуле страница загружается, из HTML удаляется обвязка (навигация, футер, скрипты, cookie-баннеры), и от оставшегося основного контента считается 64-битный SimHash. Если Hamming distance от baseline превысил порог — контент признан изменившимся, и URL автоматически уходит в IndexNow с причиной content_changed. SimHash устойчив к перестановкам и мелкой косметике, поэтому правка одного абзаца триггерит пинг, а замена иконки в шапке — нет. Это решает классическую проблему «слишком много пингов» и сберегает квоту на 429.

Событие 2. Появление страницы в sitemap

Если в sitemap.xml появился новый URL, Crawler ставит его в очередь краулинга, и при первом успешном fetch (HTTP 2xx) автоматически отправляет первичный IndexNow-пинг с причиной first_seen. Никакого ручного «добавь в индекс» не требуется.

Событие 3. Восстановление страницы после 4xx/5xx

Если URL некоторое время отдавал 404 или 5xx, а потом снова стал 2xx, Crawler инициирует «восстановительный» пинг с причиной recovered. Это полезно для блогов и медиа: обнаружили 410 на удалённой статье, потом восстановили её — IndexNow уведомит поисковики, что страница снова жива.

Догоняющий механизм: catch-up

Если пользователь добавил ключ IndexNow к проекту уже после того, как часть страниц прокраулена, без догоняющего пинга эти страницы получили бы первичный IndexNow только при следующем плановом обходе — через часы или дни. Чтобы закрыть этот разрыв, Crawler сразу после успешной валидации ключа находит все активные страницы проекта с lastPingedSnapshotId = null, берёт по каждой последний успешный снапшот и шлёт первичный пинг. Дубли исключены: страницы с lastPingedSnapshotId ≠ null намеренно пропускаются.

Что записывается в журнал

Каждый пинг сохраняется в таблице ping_log: id страницы, id снапшота, целевая система (bing или yandex), статус (success или failed), тело ответа и причина (content_changed, first_seen, recovered, catch_up и т. д.). Это позволяет в карточке страницы увидеть всю историю пингов с расшифровкой, почему именно этот пинг был отправлен.

Чтобы подключить весь этот пайплайн к своему сайту, достаточно зарегистрировать проект в панели управления, указать ключ IndexNow в настройках и положить ключ-файл в корень сайта. Дальше система делает всё сама.

Типичные ошибки реализации

Описанные ниже ошибки регулярно встречаются как при ручной интеграции, так и при использовании сторонних плагинов. Половина из них приводит к молчаливому отказу — запрос возвращает 200, а URL в индекс не попадает.

Ошибка 1. Неверный или недоступный ключ

Самый частый сценарий — ключ-файл лежит, но недоступен поисковику. Причины: закрыт Disallow: / в robots.txt для всех ботов, отдаёт 401 за basic-auth (на стейдже забыли убрать), возвращает Content-Type: application/octet-stream вместо text/plain, или содержит лишние пробелы и BOM. Проверка простая: curl -i https://example.com/<KEY>.txt должен вернуть 200 и ровно строку с ключом. Если в файле есть перевод строки в конце — это допустимо, лишний контент — нет.

Ошибка 2. Превышение лимита в 10 000 URL за запрос

Стандарт разрешает не более 10 000 URL в одном POST. Большие e-commerce-каталоги пытаются отправить весь сайт разом и получают 400. Решение — батчевать список, отправляя пачки по 1 000–5 000 URL с интервалом, и не пытаться засабмитить сайт целиком: IndexNow задуман для уведомлений о точечных изменениях, не для массового переобхода. Если нужна массовая переиндексация, отдельные части каталога логичнее обновить по триггеру «изменился прайс» или «изменилось описание».

Ошибка 3. Слишком частые запросы

Bing и Яндекс не публикуют точных RPS-лимитов, но на практике 429 начинают приходить, если домен шлёт более одного-двух POST в секунду в течение длительного времени. Особенно это видно на проектах со старой автоматизацией, отправляющей пинг по каждому HTTP-запросу к админке. Лекарство — дебаунс на стороне отправителя: одна страница не должна пинговаться чаще, чем раз в 5–10 минут даже при множественных правках подряд. В Crawler это решается тем, что пинг отправляется только при реально изменившемся SimHash.

Ошибка 4. URL не из того домена

В urlList попадают абсолютные URL с другим хостом — например, потому что в БД хранится legacy-домен или CDN-URL. Поисковик отвергает запрос с 400. Защита — нормализовать URL перед отправкой и сравнивать с host. Crawler фильтрует cross-domain URL автоматически и не пингует то, что не принадлежит проекту.

Ошибка 5. Несовпадение протокола

Если ключ-файл доступен по https://example.com/key.txt, но в urlList попадают URL вида http://example.com/page — будет 422. Это бывает на сайтах в процессе миграции на HTTPS, где часть страниц возвращает редирект 301 на https-версию. Отправляйте только конечные URL — те, по которым реально находится контент.

Ошибка 6. Перепосыл одного и того же URL

Несколько раз в сутки шлёте IndexNow по неизменившейся странице — рискуете получить 429 и временный бан на пинги от домена. Принцип «один URL — одно изменение — один пинг» работает почти всегда. В Crawler соблюдается жёстко: на каждой странице хранится lastPingedSnapshotId, и повторный пинг отправляется только если SimHash снапшота отличается от того, что был запинган в последний раз.

Ошибка 7. Пинг noindex-страниц

Поисковики не индексируют страницы с <meta name="robots" content="noindex"> или HTTP-заголовком X-Robots-Tag: noindex. Слать на них IndexNow бессмысленно и засоряет краулинговый бюджет: ответ будет 200, но страница в индекс всё равно не попадёт. Перед отправкой проверяйте директивы robots и пропускайте noindex-URL. Crawler делает это автоматически: страница с noindex не пингуется, ранее накопленные issues по такой странице подавляются.

Ошибка 8. Пропуск логирования и мониторинга

Самая обидная ошибка: IndexNow работает, но никто не смотрит, успешно ли уходят пинги. Через месяц обнаруживается, что после смены SSL-сертификата ключ-файл стал отдавать 403, и все пинги последний месяц возвращали 403 — но никто этого не видел, потому что логи не велись. Минимум — настроить алерт «доля 4xx/5xx ответов от IndexNow превысила N % за последний час». В Crawler такие проверки строятся поверх таблицы ping_log и попадают в общий мониторинг SEO-здоровья проекта.

Чек-лист внедрения

  1. Сгенерировать ключ длиной 16–32 символа из [a-z0-9].
  2. Положить <KEY>.txt в корень сайта, проверить ответ curl -i: 200 и точная строка с ключом.
  3. Открыть ключ-файл от robots.txt и любой авторизации.
  4. Подготовить функцию-обёртку, которая шлёт POST на https://www.bing.com/indexnow с правильным host, key, keyLocation и urlList.
  5. Логировать код ответа и тело — желательно в БД, не в stdout.
  6. Триггерить отправку только при реальном изменении контента (diff по SimHash или хэшу основного блока).
  7. Батчевать URL по 1 000–5 000 элементов; не отправлять более 10 000 за раз.
  8. Фильтровать noindex-страницы и URL не из основного домена.
  9. Настроить алерт на долю 4xx/5xx ответов от IndexNow за последний час.
  10. Через 2–4 недели сверить отчёт «время от публикации до индексации» с показателями до внедрения — обычно сокращение на 60–90 % для динамических сайтов.

Если делать всю эту работу руками не хочется, можно подключить проект к Crawler — система проверит ключ, выполнит догоняющий пинг для всех уже известных страниц, будет отслеживать изменения через SimHash и отправлять IndexNow только тогда, когда это действительно нужно. Все пинги попадают в журнал с указанием причины, поэтому можно в любой момент посмотреть, почему та или иная страница была отправлена в индекс.