Перейти к содержимому

Поиск Яндекса через API: умный, пакетный, Brave и Tavily

Выдача Яндекса по одному HTTP-запросу: без своего каталога в Yandex Cloud, без белых IP и VPN. Один движок доступен в трёх видах — Brave-совместимый GET, Tavily-совместимый POST и собственный пакетный формат, который отдаёт всё, что присылает Яндекс: абсолютную позицию, doc_id, язык документа, дату изменения.

Все запросы — с ключом в заголовке Authorization: Bearer <ключ> (см. Аутентификация). Полная схема параметров — в интерактивном справочнике proxy.seyka.ru/api-docs.

Эндпоинт Формат Что делает
GET /v1/search/yandex Brave Один запрос, параметры в query string, листание через offset
POST /v1/search/yandex Tavily Один запрос, тело в формате Tavily
POST /v1/search/yandex/smart Пакетный 1–50 запросов, ступень подбирается сама
POST /v1/search/yandex/sync Пакетный 1–50 запросов, всё, чего нет в кэше, — синхронно
POST /v1/search/yandex/async Пакетный 1–50 запросов в отложенном режиме, ответ 202 сразу
GET /v1/search/yandex/async/{batchId} Пакетный Забрать отложенный пакет — бесплатно
DELETE /v1/search/yandex/cache Пакетный Сбросить кэш по запросам — бесплатно
DELETE /v1/search/yandex/cache/{batchId} — Сбросить всё, что положил в кэш пакет, — бесплатно

Тот же Tavily-совместимый поиск доступен по адресам POST /v1/tavily/search и POST /search — см. Tavily-совместимый API.

Один и тот же запрос можно обслужить тремя способами, и цена зависит от того, какой сработал:

Ступень Когда отвечает
cache Такая выдача уже лежит в кэше и не устарела
async Отложенный режим Яндекса: обычно отвечает примерно за секунду
sync Синхронный запрос к Яндексу: самый дорогой, зато сразу

Ставки ступеней — на странице Цены. Как они применяются:

  • Умный поиск и совместимые эндпоинты (POST /v1/search/yandex/smart, GET /v1/search/yandex, POST /v1/search/yandex) идут по ступеням сами: сначала кэш, затем отложенный режим, и только если он не ответил примерно за 5 секунд — синхронный запрос. Оплачивается одна ступень — та, что ответила: если отложенная попытка не успела, вы платите за синхронный запрос, а не за оба.
  • POST /v1/search/yandex/sync обходит отложенный режим: запросы, которых нет в кэше, сразу идут синхронно.
  • POST /v1/search/yandex/async только ставит запросы в отложенный режим и отвечает сразу. Цена фиксируется в момент отправки, результаты забираются бесплатным GET.

Во всех случаях запрос, найденный в кэше, стоит как ответ из кэша. В умном и синхронном режимах одинаковые запросы внутри одного пакета уходят в Яндекс один раз — повторы считаются попаданием в кэш; в отложенном каждый повтор отправляется и оплачивается отдельно. В синхронном и умном режимах запрос, завершившийся ошибкой, не оплачивается; в отложенном оплата фиксируется при отправке и не возвращается, если запрос потом завершится ошибкой или истечёт. Кэш общий для всех клиентов: выдачу, которую уже получил кто-то другой, вы получите по цене кэша.

Совместимые эндпоинты (GET/POST /v1/search/yandex, POST /v1/tavily/search, POST /search) сообщают стоимость в заголовках:

Заголовок Пример Значение
X-Cost-Cents целое число Сколько списано за запрос, в копейках
X-Search-Source sync Самая дорогая ступень, которая участвовала: cache, async или sync
X-Search-Rungs cache=1,sync=1 Из чего сложилась сумма, от дешёвой ступени к дорогой

X-Search-Rungs нужен потому, что Яндекс отдаёт выдачу страницами по 100 результатов, и каждая страница — отдельный оплачиваемый поиск. Запрос на 200 результатов, где первая сотня нашлась в кэше, а вторую пришлось запросить синхронно, покажет X-Search-Source: sync и X-Search-Rungs: cache=1,sync=1.

Пакетные эндпоинты кладут ту же разбивку в тело ответа, в блок billing: cost_cents — итог в копейках, breakdown — строки по ступеням (source, count, unit_cents, cost_cents), от дешёвой к дорогой.

GET /v1/search/yandex принимает параметры Brave Search API в query string и отвечает в его формате.

Параметр По умолчанию Описание
q — Поисковый запрос, обязательный
count 10 Сколько результатов вернуть, 1–200. Больше 100 — это две страницы Яндекса и две оплаченные выборки
offset 0 Сдвиг в результатах (не в страницах), 0–100000
region — Код региона Яндекса: 225 — Россия, 213 — Москва, 2 — Санкт-Петербург. Без него или 0 — регион по IP
freshness — Ограничение по времени: pd — сутки, pw — неделя, pm — месяц, py — год
safesearch moderate off, moderate или strict
country ru Метка страны в ответе; на поиск не влияет
search_lang ru Подставляется в поле language результатов; на поиск не влияет
ui_lang ru Принимается для совместимости, не используется
Окно терминала
curl "https://proxy.seyka.ru/v1/search/yandex?q=погода+москва&count=10&region=213" \
-H "Authorization: Bearer $SEYKA_API_KEY"
{
"type": "search",
"query": { "original": "погода москва", "altered": "погода москва", "language": "ru", "country": "ru" },
"web": {
"type": "search",
"family_friendly": true,
"results": [
{
"title": "Погода в Москве на сегодня",
"url": "https://example.ru/weather/moscow",
"description": "Прогноз погоды в Москве…",
"language": "ru",
"family_friendly": true,
"meta_url": { "…": "…" },
"extra_snippets": ["…"]
}
]
}
}

Ответ — только поля схемы Brave: позиции, doc_id, язык документа и остальные данные Яндекса в него не попадают. Если они нужны, используйте пакетный формат.

POST /v1/search/yandex принимает тело Tavily Search и отвечает в его формате.

Поле Описание
query Поисковый запрос, обязательное
max_results Сколько результатов вернуть, по умолчанию 10, не больше 200
region Код региона Яндекса, как в GET
include_domains / exclude_domains Оставить или убрать домены (включая поддомены)
search_depth Принимается для совместимости, ни на что не влияет

Остальные поля Tavily (topic, include_answer, freshness и т. п.) принимаются и игнорируются — запрос не ломается, но и эффекта нет. Ограничение по времени есть только в GET и пакетном формате.

Окно терминала
curl -X POST "https://proxy.seyka.ru/v1/search/yandex" \
-H "Authorization: Bearer $SEYKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "лучшие рестораны москвы", "max_results": 5, "region": 213}'
{
"query": "лучшие рестораны москвы",
"results": [
{
"title": "Лучшие рестораны Москвы — рейтинг",
"url": "https://example.ru/restaurants",
"content": "Рейтинг ресторанов Москвы по отзывам посетителей…",
"score": 1
}
]
}

score выводится из порядка результатов (1.0 у первого, дальше по убыванию), а не из оценки релевантности: Яндекс её не отдаёт.

POST /v1/search/yandex/smart, POST /v1/search/yandex/sync и POST /v1/search/yandex/async принимают одно и то же тело: от 1 до 50 запросов, общие параметры выносятся в defaults, каждый запрос может их переопределить. Больше 50 запросов — ответ 413.

Поле Описание
queries[].query Поисковый запрос, обязательное
queries[].max_results 1–200, по умолчанию 10. Больше 100 — две страницы и две оплаченные выборки
queries[].region Код региона Яндекса
queries[].freshness pd, pw, pm или py
queries[].safesearch off, moderate или strict
queries[].include_domains / exclude_domains Фильтр доменов; задаётся только у запроса, не в defaults
defaults region, max_results, freshness, safesearch для всех запросов пакета
cache_ttl Максимальный возраст выдачи из кэша и срок хранения новой, в секундах. По умолчанию 86400 (24 часа), потолок — 30 дней, 0 — не брать из кэша
language / country Метки в ответе; на поиск не влияют
Окно терминала
curl -X POST "https://proxy.seyka.ru/v1/search/yandex/smart" \
-H "Authorization: Bearer $SEYKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"queries": [
{ "query": "ремонт квартир" },
{ "query": "натяжные потолки", "max_results": 50 }
],
"defaults": { "region": 213, "max_results": 20 }
}'
{
"id": "835f2bfa-7c5a-462d-b080-cdee801d23d8",
"count": 1,
"done": true,
"counts": { "pending": 0, "done": 1, "error": 0 },
"billing": { "cost_cents": …, "breakdown": [{ "source": "cache", "count": 1, "unit_cents": …, "cost_cents": … }] },
"items": [
{
"query": "ремонт квартир",
"status": "done",
"source": "cache",
"fetched_at": 1786669181,
"results": [
{
"pos": 1,
"doc_id": "ZDB5DBD400EA724B7",
"title": "Ремонт квартир в Москве: цены",
"url": "https://example.ru/price",
"domain": "example.ru",
"snippet": "Актуальные цены на ремонт квартир…",
"modtime": "20250827T120000",
"lang": "ru",
"size": 4412,
"mime_type": "text/html",
"charset": "utf-8",
"saved_copy_url": "https://yandexwebcache.net/…"
}
],
"meta": { "found": 24000000, "reqid": "…", "is_local": true }
}
]
}
Поле Что это
id Идентификатор пакета: для GET /v1/search/yandex/async/{batchId} и DELETE /v1/search/yandex/cache/{batchId}
done Ни один запрос не остался в работе. Не значит, что все успешны, — смотрите status каждого
counts Сколько запросов в работе, готово и с ошибкой
items[].status queued, pending, done, error или expired
items[].source Ступень, которая ответила: cache, async или sync
items[].results Результаты; [] — запрос ничего не нашёл, null — ещё не готов
items[].error Текст ошибки, если status — error
items[].meta found — сколько документов нашёл Яндекс, reqid — идентификатор для поддержки, is_local — выдача локализована, effective_request — что Яндекс применил на самом деле

У результата: pos — абсолютная позиция в выдаче (не индекс в массиве: страницы склеиваются и фильтруются), doc_id — идентификатор документа у Яндекса, domain, snippet и passages, modtime — когда документ менялся, lang — язык документа, size, mime_type и charset, saved_copy_url — сохранённая копия у Яндекса.

Ошибка одного запроса не роняет пакет: он получает status: "error", остальные отвечают как обычно.

POST /v1/search/yandex/sync отвечает только готовыми результатами: каждый запрос, которого нет в кэше, сразу идёт в синхронный режим Яндекса. Удобен, когда ответ нужен немедленно и ждать отложенный режим нет смысла.

POST /v1/search/yandex/async ставит запросы в отложенный режим и отвечает 202 с id пакета. Заберите результаты, когда удобно, через GET /v1/search/yandex/async/{batchId} — чтение бесплатное, его можно повторять сколько угодно.

Окно терминала
# 1. Отправить пакет — ответ 202 приходит сразу
curl -X POST "https://proxy.seyka.ru/v1/search/yandex/async" \
-H "Authorization: Bearer $SEYKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"queries": [{"query": "ремонт квартир"}], "defaults": {"region": 213}}'
# 2. Забрать результаты по id из ответа
curl "https://proxy.seyka.ru/v1/search/yandex/async/835f2bfa-7c5a-462d-b080-cdee801d23d8" \
-H "Authorization: Bearer $SEYKA_API_KEY"
  • Пакет хранится 12 часов; запрос, который не успел за это время, получает expired.
  • Результаты отложенного пакета хранятся в кэше не меньше 12 часов, даже если cache_ttl меньше.
  • Пакет виден только аккаунту, который его создал (любому его ключу). Чужой или несуществующий batchId возвращает 404.
  • Блока billing в ответе на чтение нет: всё оплачено при отправке.

Выдача по умолчанию хранится 24 часа; в пакетах срок задаёт cache_ttl (до 30 дней). Совместимые эндпоинты и POST /v1/search/yandex/smart без cache_ttl берут любую ещё живую запись — так дешевле всего. Заголовок Cache-Control: no-cache на поиск не действует: у поиска свой кэш выдачи.

Чтобы получить свежую выдачу, сбросьте кэш явно:

Окно терминала
# По запросам — тело такое же, как у пакетного поиска
curl -X DELETE "https://proxy.seyka.ru/v1/search/yandex/cache" \
-H "Authorization: Bearer $SEYKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"queries": [{"query": "ремонт квартир", "region": 213, "max_results": 200}]}'
# Всё, что положил в кэш ваш пакет
curl -X DELETE "https://proxy.seyka.ru/v1/search/yandex/cache/835f2bfa-7c5a-462d-b080-cdee801d23d8" \
-H "Authorization: Bearer $SEYKA_API_KEY"
{ "requested": 2, "purged": 2 }

Указывайте те же region, freshness, safesearch и max_results, что и в исходном поиске: сбрасываются страницы, которые покрывает это окно, поэтому запрос без max_results очистит только первую сотню. Кэш общий, поэтому сброс затрагивает всех, кто получает ту же выдачу. Сброс бесплатный.

Яндекс отдаёт выдачу страницами по 100 результатов, поэтому count или max_results больше 100 — это две выборки и две ступени в X-Search-Rungs. Соседние страницы Яндекса перекрываются; повторы удаляются, и запрос на 200 обычно возвращает чуть меньше 200 результатов.

offset в GET /v1/search/yandex отсчитывается в результатах. Окно, которое пересекает границу сотни (например, offset=90&count=20), затрагивает две страницы, и обе оплачиваются.

  • region — код региона Яндекса: 225 — Россия, 213 — Москва, 2 — Санкт-Петербург, 65 — Новосибирск. Без него или с 0 регион определяется по IP. Справочник — в документации Яндекса.
  • freshness — pd, pw, pm, py. Запрос со свежестью — это отдельный поиск, а не фильтр поверх старого, и кэшируется он отдельно.
  • include_domains / exclude_domains применяются к уже полученной выдаче, а не отправляются в Яндекс: смена фильтра не требует новой выборки и стоит как ответ из кэша. Домен совпадает вместе с поддоменами: habr.com включает career.habr.com, но не nothabr.com.

Язык поиска определяется по запросу: запрос с кириллицей ищется по русскоязычной выдаче, без неё — по международной.

  • 400 — пустой запрос в Tavily-совместимом POST; 422 — пустой или отсутствующий q в Brave-совместимом GET и любой неверный параметр (например, count больше 200). В пакете пустой запрос получает status: "error", остальные выполняются как обычно.
  • 413 — в пакете больше 50 запросов.
  • 429 — исчерпана квота поиска Яндекса или Яндекс сам ответил отказом по частоте. Совместимые эндпоинты отвечают 429; в умном и синхронном пакете такой запрос получает status: "error". В отложенном пакете отказ повторяется, пока не истечёт срок жизни пакета, и тогда запрос получает status: "expired". Повторите позже.
  • 404 — пакет не найден или принадлежит другому аккаунту.

Остальные коды — в разделе Ошибки.

Поиск оплачивается по ступени, которая ответила; чтение отложенного пакета и сброс кэша бесплатны. Ставки — на странице Цены.