Узкий актуальный справочник по Yandex Search API Wordstat v2: методы, схемы, авторизация, квоты, регионы, устройства и динамика. Для рекламного процесса сначала использовать yandex-direct-unified.
Installs into .claude/skills of the current project.
Are you the author of Yandex Wordstat?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/hashgraph-online-yandex-wordstat)
---
name: yandex-wordstat
description: "Узкий актуальный справочник по Yandex Search API Wordstat v2: методы, схемы, авторизация, квоты, регионы, устройства и динамика. Для рекламного процесса сначала использовать yandex-direct-unified."
---
# Yandex Wordstat API v2
Этот файл не задает порядок сбора семантики, смысловые решения, минус-слова, структуру кампаний или готовность к сборке.
Для любых задач Яндекс.Директа, ключевых фраз, SQR, семантики и стоп-слов сначала открыть `yandex-direct-unified`, его обязательные references и `keyword-collection-runbook.md`. Этот файл использовать только как справочник по текущему Wordstat API.
## Канонический транспорт
- Базовый адрес: `https://searchapi.api.cloud.yandex.net`.
- Текущая версия: синхронный REST API v2.
- Старый `https://api.wordstat.yandex.net/v1/*` и метод `userInfo` не использовать.
- `folderId` передается в теле каждого запроса.
- Для локального клиента рабочий сбор идет по целевому гео; вся Россия может использоваться только как явно обозначенный фон.
Если целевое гео исключает крупный дочерний город или отдельные дочерние регионы из более широкого узла, сначала прочитать `getRegionsTree` и собрать точный список разрешённых дочерних `id`. Комбинированный узел не заменяет исключающее гео: узел «Москва и область» не доказывает спрос по области без Москвы. Если точный набор дочерних регионов нельзя собрать или проверить, это блокер гео, а не повод продолжать по широкому региону.
Если запрос падает до ответа сервиса из-за TLS, проверки сертификата, несовпадения хоста и сертификата или другой ошибки транспорта, это блокер транспорта. Нельзя отключать проверку сертификатов, подставлять старый адрес или заменять Wordstat подсказками поиска, сниппетами выдачи, HTML или догадкой. Сохранить состояние по маскам, сырые ответы, манифест и журнал повторов, починить официальный транспорт и только потом продолжать.
HTML и живой интерфейс Wordstat допустимы только для диагностики страницы, но не как источник статистики и не как запасной транспорт. Поле ввода, заголовок, период, общее число и таблица обновляются несинхронно, поэтому пауза не доказывает актуальность. Числа из интерфейса отбрасываются и заново получаются через выбранного провайдера: официальный API v2 или явно названный сторонний провайдер.
Целевое происхождение данных: для каждой попытки свой `query_id` внутри `run_id`, сырой запрос и сырой ответ сохраняются без перезаписи, в манифесте — метод, точная фраза, гео, устройство, время, статус, пути сырых файлов и SHA-256 каждого файла; каждая применяемая строка ссылается на успешный `query_id`. Штатные сборщики модуля пишут это частично: облачный сохраняет сырой ответ на маску и тип артефакта и перезаписывает строку манифеста при повторе, XMLRiver ведёт журнал попыток с SHA-256 сырых ответов. Облачный сборщик повторяет запрос внутри себя после 429 и 5xx и сохраняет только последний ответ, поэтому трасса попыток у него всегда неполная: в отчёте так и писать, а хеши сырых файлов и копию манифеста каждого запуска сохранять для проверки того, что сохранено. Полную трассу каждой попытки даёт только сборщик, который сам пишет каждую попытку (так устроен журнал XMLRiver).
## Авторизация
Разрешены два варианта:
1. API-ключ: заголовок `Authorization: Api-Key <key>`.
2. IAM-токен: заголовок `Authorization: Bearer <iam-token>`.
Для API-ключа нужна область `yc.search-api.execute`, а сервисному аккаунту или пользователю — роль `search-api.webSearch.user` на нужный каталог.
Секреты нельзя печатать, передавать в аргументах процесса или сохранять в raw/manifest. Канонический credential-файл должен находиться в закрытом каталоге `700`, иметь владельца рабочего пользователя и права `600`.
## Общие перечисления
Устройства:
- `DEVICE_ALL`;
- `DEVICE_DESKTOP`;
- `DEVICE_PHONE`;
- `DEVICE_TABLET`.
Если передается список `devices`, в нем не более трех значений. Для `topRequests` и `dynamics` список `regions` содержит не более 100 строковых ID.
## Методы
### `POST /v2/wordstat/topRequests`
Назначение: спрос за последние 30 дней, популярные вложенные фразы и ассоциации.
Запрос:
```json
{
"phrase": "обязательная фраза до 400 символов",
"numPhrases": 2000,
"regions": ["регион"],
"devices": ["DEVICE_ALL"],
"folderId": "каталог"
}
```
`numPhrases`: от 1 до 2000.
Ответ:
```json
{
"totalCount": 0,
"results": [{"phrase": "...", "count": 0}],
"associations": [{"phrase": "...", "count": 0}]
}
```
Ассоциаций в одном ответе бывает не более 20. Для Директа и `results`, и `associations` сохраняются как raw и дальше проходят только workflow `yandex-direct-unified`.
### `POST /v2/wordstat/dynamics`
Назначение: динамика спроса.
Запрос:
```json
{
"phrase": "обязательная фраза до 400 символов",
"period": "PERIOD_MONTHLY",
"fromDate": "2026-01-01T00:00:00Z",
"toDate": "2026-07-01T00:00:00Z",
"regions": ["регион"],
"devices": ["DEVICE_ALL"],
"folderId": "каталог"
}
```
Периоды: `PERIOD_MONTHLY`, `PERIOD_WEEKLY`, `PERIOD_DAILY`. Даты передаются в RFC3339. Для недельной и месячной динамики допустим только оператор `+`; для дневной поддерживаются все операторы Wordstat.
Ответ:
```json
{
"results": [{"date": "2026-01-01T00:00:00Z", "count": 0, "share": 0.0}]
}
```
### `POST /v2/wordstat/regions`
Назначение: распределение спроса за последние 30 дней.
Запрос:
```json
{
"phrase": "обязательная фраза до 400 символов",
"region": "REGION_ALL",
"devices": ["DEVICE_ALL"],
"folderId": "каталог"
}
```
Значения `region`: `REGION_ALL`, `REGION_CITIES`, `REGION_REGIONS`. Путь `/v2/wordstat/regionsDistribution` неверен: это было смешение имени gRPC-метода с REST-путем.
Ответ:
```json
{
"results": [
{"region": "ID", "count": 0, "share": 0.0, "affinityIndex": 0.0}
]
}
```
### `POST /v2/wordstat/getRegionsTree`
Назначение: дерево поддерживаемых регионов.
Запрос содержит только `folderId`:
```json
{"folderId": "каталог"}
```
Ответ:
```json
{
"regions": [
{"id": "ID", "label": "Название", "children": []}
]
}
```
Метод официально не тарифицируется, но лишние вызовы запрещены.
## Квоты и повтор
- Не более 10 запросов в секунду.
- Не более 100 запросов в час суммарно для `topRequests`, `dynamics`, `regions` и `getRegionsTree`; дерево регионов имеет нулевую стоимость, но потребляет запрос квоты.
- В v2 нет `userInfo` и ответа с остатком дневной квоты.
- Сборщик обязан вести локальный почасовой учет, ограничивать скорость и обрабатывать HTTP 429/`Retry-After`.
- При ограничении сохраняются raw, manifest, закрытые маски и очередь незакрытых масок. После разрешенного ожидания сбор продолжается с незакрытого элемента без дублей.
- Ошибка целевой маски должна попасть в `wordstat_errors_retry_log.tsv`; волна не закрывается, пока повтор не дал результат либо маска явно не помечена `blocked` с причиной.
- Конечная дата `dynamics` — не позже последнего завершённого периода выбранной детализации. Ответ 400 «неверная конечная дата» исправляется датой, а не повтором того же запроса.
- Файлы блокировки и состояния сборщика пишутся атомарно: сначала полный временный файл с `run_id`, номером процесса, временем, рабочей папкой и целевой маской, затем переименование. Пустой файл блокировки как промежуточное состояние запрещён. Владение не доказывается одним номером процесса: устаревшая блокировка снимается после сверки манифеста, сырых ответов и журнала повторов и явной записи о восстановлении, без потери незакрытых масок.
- Если квоты официального API не хватает на объём задачи, Wordstat можно собрать через стороннего провайдера XMLRiver (навык xmlriver-serp-research): платно с баланса, без часового лимита; ограничение — число потоков аккаунта и ошибки 110 и 115. Это неофициальный разбор интерфейса Wordstat со своей схемой ответа. Числа двух провайдеров хранятся с пометкой источника и в один ряд не сводятся. Лимит 100 запросов в час официального API на XMLRiver не переносится, а лимит потоков XMLRiver — на официальный API.
## Нулевой спрос
ProtoJSON может законно опускать пустые `results`, пустые `associations` и нулевой `totalCount`; при разборе они нормализуются в `[]`, `[]` и `0`. Поле `int64 totalCount` штатно может приходить строкой из цифр. Отрицательные, дробные и повреждённые значения не принимаются как спрос.
Корректный JSON-объект `{}` для `topRequests` — допустимое представление нулевых значений; он сохраняется как доказанный `no_demand_found`: `exact_phrase_count=0`, `mask_total_count=0`, `evidence_kind=zero`. То же для явно переданных нулевого `totalCount`, пустых `results` и пустых `associations`. Для `dynamics` и `regions` валидные нулевые значения тоже не ошибка схемы. Нулевой результат сохраняется с фразой, гео, устройством, методом, временем, путём к сырому ответу и строкой в сводке масок. Ошибки — повреждённый JSON, неверные типы, отрицательные счётчики, сбой HTTP, транспорта или TLS, сбой квоты и незакрытый повтор по целевой маске.
Доказательства не смешиваются: `exact_phrase_count` берётся только из строки `results`, чья фраза после нормализации совпадает с маской; `mask_total_count` — только из `totalCount`; `evidence_kind` равен `exact_row`, `mask_total_only` или `zero`. Строки `associations` и общий спрос маски не выдаются за спрос фразы. Частотность без операторов включает словоформы и более длинные запросы, поэтому `exact_phrase_count` — не «точная» частота: рядом хранится операторная форма маски и вид частотности (`frequency_kind`: `broad` без операторов, `quoted` в кавычках, `exact` в кавычках с `!`). Точный спрос фразы — только из маски с операторами.
## Испытания
Тесты и проверки, которые вызывают код сборщика, сначала доказывают сетевую изоляцию: установлен поддельный транспорт, настоящий токен отключён, запрос не может уйти в настоящий API. Если подмена не сработала и возможен настоящий запрос — это дефект безопасности, а не безвредный сбой: остановить проверку, сохранить состояние, восстановить изоляцию и повторить на доказанно поддельном транспорте.
## Операторы
Поддерживаются операторы Wordstat `-`, `+`, `!`, кавычки, квадратные и круглые скобки. Их семантика применяется по официальной документации Wordstat. Операторная форма маски не является автоматически готовым ключом Директа.
Сборщики модуля читают файл масок построчно и делят строку по табуляции без разбора кавычек CSV. Поэтому маски с операторами записываются как есть, без экранирования: `"купить стол"` — ровно эти символы в строке; `csv.writer` с настройками по умолчанию удвоит кавычки и испортит оператор. Перед сбором прочитать файл тем же способом (строка → `split("\t")`) и сверить, что маска совпадает с задуманной. В сыром ответе сохраняется именно та маска, которую собирались проверить.
## Правила для Директа
1. Сначала `intake-gate`, product/routing/protected layers и pre-Wordstat извлечение синонимов.
2. Затем raw Wordstat/SQR.
3. После raw: `SAFE_STOP` только с protected-check, сохраняемый prefilter, затем полный построчный смысловой разбор.
4. Скрипт не имеет права выбирать ключи, ставить semantic verdict или объявлять coverage `PASS`.
5. Каждая raw-строка получает `candidate_id` либо явное решение с причиной.
6. Live apply, минус-слова, черновики и любые записи в Директ требуют отдельного явного разрешения пользователя.
## Первоисточники
- https://aistudio.yandex.ru/docs/ru/search-api/concepts/wordstat.html
- https://aistudio.yandex.ru/docs/ru/search-api/api-ref/Wordstat/
- https://github.com/yandex-cloud/cloudapi/blob/master/yandex/cloud/searchapi/v2/wordstat_service.proto
- XMLRiver, Wordstat: https://xmlriver.com/apiwordstatnew/apiwn-about/
- XMLRiver, метод words: https://xmlriver.com/apiwordstatnew/apiwn-words/
- XMLRiver, метод history: https://xmlriver.com/apiwordstatnew/apiwn-history/
- XMLRiver, коды ошибок: https://xmlriver.com/apiwordstatnew/apiwn-errors/