Зачем это, если кабинет уже есть
Кабинет и API решают разные задачи. В кабинет вы заходите руками, когда что-то заподозрили. API нужен, чтобы завод работал без вас.
| Задача | Через кабинет | Через API |
|---|---|---|
| Отправить новую статью на переобход | руками, по одному адресу | автоматически при публикации |
| Найти «быстрые победы» (позиции 11–20) | выгружать CSV и сортировать | отчёт приходит сам |
| Заметить, что страницы выпали из индекса | если вспомнили зайти | алерт в Telegram в тот же день |
| Новые темы из реальных запросов | смотреть глазами раз в месяц | подмешивается в семантику каждую неделю |
| Отправить карту сайта после релиза | руками | одной строкой в деплое |
Что понадобится
- Сайт уже добавлен и подтверждён в Яндекс.Вебмастере и Google Search Console. API не умеет подтверждать права за вас.
- Аккаунт Яндекса — тот же, под которым подтверждали сайт.
- Аккаунт Google — тот же, под которым подтверждали ресурс. Это важнее, чем кажется: строка подтверждения уникальна для пары «аккаунт + ресурс».
- 15–30 минут. Яндекс — минут семь, Google — от десяти до двадцати в зависимости от маршрута.
market.scope: intl) Яндекс не нужен вовсе — хватит одного Google. Для российского нужны оба.Яндекс.Вебмастер: токен за 7 минут
Токен Вебмастера — это не пароль от Яндекса. Это OAuth-токен приложения, которое вы сами создаёте за минуту. Звучит страшнее, чем есть.
- Создайте приложение. oauth.yandex.ru/client/new. Название — любое, например «SEO-завод». Иконка не нужна.
- Платформа — «Веб-сервисы». В поле Redirect URI вставьте ровно это:
https://oauth.yandex.ru/verification_code - Доступ к данным — два права:
webmaster:hostinfoиwebmaster:verify. Первое даёт читать данные сайта, второе — отправлять страницы на переобход. Больше ничего отмечать не надо. - Создайте приложение и скопируйте ClientID — он появится на странице приложения.
- Получите токен. Подставьте ClientID в адрес ниже, откройте его в браузере и скопируйте токен со страницы.
https://oauth.yandex.ru/authorize?response_type=token&client_id=ВАШ_CLIENT_ID
Яндекс: где взять user_id и host_id
Все адреса API выглядят как /v4/user/{user_id}/hosts/{host_id}/…, поэтому эти два значения нужны при каждом запросе. Вопрос только в том, кто их подставляет.
Если вы работаете на нашем SEO-заводе — достаточно токена. Завод сам спрашивает у API свой user_id, сам находит нужный сайт по домену из site.config.yml и предпочитает подтверждённое https-зеркало. Две переменные в .env — это кэш, чтобы не ходить лишний раз, а не требование: наши собственные сайты живут с одним заполненным токеном. Если пишете свою интеграцию — доставайте значения сами, ниже как.
Идентификатор сайта угадать нельзя. Он выглядит как https:example.ru:443 — схема, хост и порт через двоеточие, без слэшей. Именно поэтому его получают списком, а не собирают из адреса сайта руками.
# 1. Свой user_id
curl -s -H "Authorization: OAuth ВАШ_ТОКЕН" \
https://api.webmaster.yandex.net/v4/user/
# → {"user_id": 12345678}
# 2. Список сайтов с их идентификаторами
curl -s -H "Authorization: OAuth ВАШ_ТОКЕН" \
https://api.webmaster.yandex.net/v4/user/12345678/hosts/
# → "host_id": "https:example.ru:443", "verified": true
curl.exe. Иначе PowerShell подставит вместо curl свой Invoke-WebRequest и ругнётся на -H — выглядит так, будто сломан запрос, хотя сломана только команда.OAuth, а не Bearer. Это общая черта Яндекса и самая частая ошибка тех, кто пришёл из мира Google. Поставите Bearer по привычке — получите 403 и будете долго искать проблему не там.Google: два маршрута
У Google есть два способа дать программе доступ, и они принципиально разные по цене обслуживания.
| А — сервисный аккаунт | Б — OAuth | |
|---|---|---|
| Настройка | 10 минут | 20 минут |
| Срок жизни доступа | не истекает | 7 дней или бессрочно — см. ниже |
| Нужен браузер при настройке | нет | да, разовый вход |
| Годится для сервера без GUI | да | только после разовой настройки на своей машине |
| Риск | GSC не всегда принимает email сервисного аккаунта | забыть опубликовать приложение — доступ умрёт через неделю |
Маршрут А — сервисный аккаунт
- Создайте проект. console.cloud.google.com → выпадающий список проектов вверху → New Project. Название любое.
- Включите API. В поиске консоли вбейте Google Search Console API → Enable. Без этого шага все запросы будут падать, даже с верным ключом.
- Создайте сервисный аккаунт. В поиске — Service Accounts → Create Service Account. Роли на этом шаге не нужны, жмите «Готово».
- Скачайте ключ. Откройте созданный аккаунт → вкладка Keys → Add Key → Create new key → JSON. Файл скачается один раз — положите его рядом с проектом и никогда не коммитьте в git.
- Главный шаг: дайте роботу права в Search Console. Откройте GSC → Настройки → Пользователи и разрешения → Добавить пользователя. Вставьте email из скачанного JSON (поле
client_email, выглядит какчто-то@проект.iam.gserviceaccount.com), разрешение — Владелец.
Маршрут Б — OAuth
- Проект и API — те же первые два шага, что в маршруте А.
- Настройте экран согласия. APIs & Services → OAuth consent screen, тип External. Заполните название и почту поддержки.
- Опубликуйте приложение. На том же экране — кнопка Publish app, статус должен стать In production. Не пропускайте этот шаг, объяснение — в следующем разделе.
- Создайте OAuth Client ID. Credentials → Create Credentials → OAuth client ID, тип приложения — Desktop app. Скачайте JSON.
- Обменяйте на refresh-токен. Один раз запустите скрипт из пакета — он откроет браузер, попросит войти под аккаунтом-владельцем ресурса и сам допишет три строки в
.env.
cd путь-к-заводу
./venv-python engine/seo-agent/modules/gsc_oauth_setup.py
# допишет в .env:
# GSC_OAUTH_REFRESH_TOKEN
# GSC_OAUTH_CLIENT_ID
# GSC_OAUTH_CLIENT_SECRET
Ловушка на 7 дней
Самая дорогая ошибка в этом гайде — и её почти невозможно заметить сразу, потому что всё работает. Неделю.
Проект Google Cloud с экраном согласия типа External и статусом публикации «Testing» выдаёт refresh-токен, который истекает через 7 дней.
— документация Google по OAuth 2.0
Что происходит на практике: вы настраиваете доступ, видите данные Google в отчётах, радуетесь. Через неделю блок «трафик из Google» тихо пустеет с ошибкой invalid_grant: Token has been expired or revoked. Остальные модули при этом работают, поэтому поломку замечают не сразу.
Лечится одним кликом: Google Cloud Console → OAuth consent screen → Publish app → статус In production. После этого refresh-токен бессрочный. Если токен уже успел умереть — опубликуйте приложение и перевыпустите токен скриптом из шага 5.
Проверка живыми запросами
Не верьте настройке на слово — проверьте каждый доступ одним запросом.
curl -s -H "Authorization: OAuth ВАШ_ТОКЕН" \
"https://api.webmaster.yandex.net/v4/user/USER_ID/hosts/HOST_ID/recrawl/quota"
# → {"daily_quota": 150, "quota_remainder": 150}
curl -s -H "Authorization: Bearer ВАШ_ACCESS_ТОКЕН" \
https://www.googleapis.com/webmasters/v3/sites
# → "siteUrl": "sc-domain:example.ru", "permissionLevel": "siteOwner"
curl -s -X PUT -H "Authorization: Bearer ВАШ_ACCESS_ТОКЕН" -H "Content-Length: 0" \
"https://www.googleapis.com/webmasters/v3/sites/sc-domain%3Aexample.ru/sitemaps/https%3A%2F%2Fexample.ru%2Fsitemap.xml"
%3A и %2F. Забыли закодировать — получите 404 на ровном месте.Грабли
Яндекс
- 401 и 403 лечатся противоположным. 401 — токен протух, нужен новый. 403 — токен живой, но прав на этот сайт нет: он не подтверждён в Вебмастере под этой учётной записью. Если перепутать, будете бесконечно перевыпускать рабочий токен.
- Массивы передаются повторяющимися ключами, а не через запятую:
query_indicator=TOTAL_SHOWS&query_indicator=TOTAL_CLICKS. Ошибка тихая — параметр просто игнорируется, а вы смотрите на пустые цифры. - Формат ошибок свой:
{error_code, error_message}. У Метрики он другой, общим кодом не разберёте. - Троттлинг — это не только 429. Встречается и 420, а часть лимитов приходит кодом ошибки, а не статусом. Считайте троттлингом оба статуса плюс коды с
QUOTAиLIMIT. - Квота переобхода конечная — обычно порядка сотни адресов в сутки. Не гоняйте в неё весь сайт после каждой правки.
- Запись в DNS — только половина подтверждения. Google не сканирует DNS сам: пока вы не нажали «Подтвердить» в интерфейсе, ресурс остаётся неподтверждённым, даже если запись давно разошлась. Мы на этом потеряли час.
- Подтверждать надо в том же аккаунте, под которым потом будет работать токен. Строка проверки уникальна для пары «аккаунт + ресурс».
- Ресурс-домен и ресурс-адрес — разные вещи.
sc-domain:example.ruпокрывает все поддомены и протоколы, но требует подтверждения через DNS.https://example.ru/подтверждается файлом, но покрывает только эту версию адреса. - Ускоренной индексации через Indexing API не существует. Этот API официально работает только с вакансиями и прямыми трансляциями. Всё, что продаётся под видом «мгновенной индексации в Google», в лучшем случае делает то же, что вы сделаете руками. Для обычных страниц остаётся карта сайта, перелинковка и ручная отправка в кабинете.
- IndexNow Google не поддерживает. Его понимают Яндекс и Bing — это по-прежнему полезно, просто не для Google.
Allow: для файла подтверждения и ключа IndexNow. Иначе поисковик не сможет их прочитать и подтверждение не пройдёт.Куда вставлять и как проверить
Все значения — только в .env рядом с конфигом сайта. В site.config.yml, документации и отчётах должны быть указатели, а не сами ключи. Файл .env обязан быть в .gitignore.
./venv-python engine/seo-agent/orchestrator.py doctor
doctor покажет по каждому ключу «задан / не задан» и что из-за отсутствия выключено. Значения он не печатает — это сделано намеренно, чтобы вывод можно было спокойно показать кому угодно.
Что это включает в заводе
| Ключ | Что заработает | Что будет без него |
|---|---|---|
YANDEX_WEBMASTER_TOKEN | запросы Яндекса, переобход новых страниц, алерты по индексации | статьи индексируются медленнее, данных Яндекса нет |
GSC_OAUTH_REFRESH_TOKEN | трафик и запросы Google, «быстрые победы» по позициям 11–20 | семантика без данных Google, быстрые победы не считаются |
YANDEX_CLOUD_API_KEY | живая частотность Wordstat при сборе тем | частоты только из вебмастеров — новые темы не найти |
INDEXNOW_KEY | мгновенный пинг новых адресов в Яндекс и Bing | ждёте планового обхода робота |
Ключ Wordstat — отдельная инструкция
Живая частотность собирается не через Вебмастер, а через Yandex Cloud Search API — там свои шаги, свой Folder ID и свои грабли. Разобрал отдельно: Wordstat API за 15 минут.
Источники
- Яндекс: авторизация в API Вебмастера — права
webmaster:hostinfoиwebmaster:verify, срок жизни токена 6 месяцев. - Google: OAuth 2.0 — правило про 7 дней для статуса «Testing» и лимит 100 refresh-токенов.
- Google: отправка карты сайта — метод, scope и формат адреса.
- Хабр: устройство MCP-сервера над API Вебмастера — практические грабли API v4: заголовок
OAuthвместоBearer, разница 401 и 403, форматhost_id, повторяющиеся ключи в массивах. - Хабр: Google Indexing API для SEO-специалиста — путь с сервисным аккаунтом и делегированием прав в Search Console.
Читать дальше
Все гайды рабочие: каждый — то, что реально крутится у меня, а не пересказ документации.