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

Яндекс Поиск

Выдача Яндекса за один HTTP-запрос: без корпоративного договора, без белых IP, без VPN. Есть два совместимых интерфейса — Tavily и Brave Search — и собственный, который отдаёт всё, что присылает Яндекс.

Окно терминала
curl -X POST "https://proxy.unoapi.ru/v1/search/yandex/smart" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"queries": [{"query": "нейросети", "max_results": 10}], "defaults": {"region": 225}}'
{
"count": 1,
"done": true,
"billing": { "cost_cents": 6, "breakdown": [{ "source": "async", "count": 1, "unit_cents": 6, "cost_cents": 6 }] },
"items": [{
"query": "нейросети",
"status": "done",
"source": "async",
"results": [{ "pos": 1, "title": "", "url": "", "domain": "", "snippet": "", "lang": "ru" }]
}]
}

source говорит, как запрос обслужен, cost_cents — во сколько это обошлось. Здесь ответил отложенный режим Яндекса: 6 копеек, около секунды — обычный исход на холодном кэше. sync за 60 копеек включается только тогда, когда отложенный не успел за 5 секунд. Повторите тот же запрос — увидите cache и 1 копейку.

Уже есть код под Tavily или Brave? Меняйте только базовый URL — совместимые форматы работают через тот же движок и то же ценообразование.

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

Совместимые эндпоинты — обёртки над тем же поиском: тот же кэш, тот же отложенный режим, то же ценообразование. Менять в вашем коде ничего не нужно.

Три ставки, по тому, кто фактически ответил:

Ставка За 1000 Когда применяется
cache 10 ₽ Выдача уже лежит у нас и не устарела
async 60 ₽ Отложенный режим Яндекса — около секунды
sync 600 ₽ Синхронный запрос: дороже, зато отвечает сразу

Порядок такой: сначала кэш, потом отложенный режим, и только если он не ответил за 5 секунд — синхронный запрос.

Платите вы одну ставку — ту, по которой запрос прошёл. Если отложенная попытка не успела и пришлось идти синхронно, в счёт попадут 60 копеек, а не 6 + 60: неудавшаяся попытка наша, а не ваша. Кэш тоже общий — выдачу, за которую заплатил один запрос, получает следующий такой же.

В ответе приходят три заголовка:

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

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

У пакетных эндпоинтов та же разбивка приходит в теле:

"billing": {
"cost_cents": 1,
"breakdown": [{ "source": "cache", "count": 1, "unit_cents": 1, "cost_cents": 1 }]
}

До 50 запросов за вызов. Общие параметры выносятся в defaults, каждый запрос может их переопределить.

Окно терминала
curl -X POST "https://proxy.unoapi.ru/v1/search/yandex/smart" \
-H "Authorization: Bearer YOUR_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": 1,
"breakdown": [{ "source": "cache", "count": 1, "unit_cents": 1, "cost_cents": 1 }]
},
"items": [
{
"query": "ремонт квартир",
"status": "done",
"source": "cache",
"fetched_at": 1786669181,
"results": [
{
"pos": 1,
"doc_id": "ZDB5DBD400EA724B7",
"title": "Ремонт квартир в Москве: прайс-лист 2026",
"url": "https://titanremont.ru/price",
"domain": "titanremont.ru",
"snippet": "Актуальный прайс-лист на ремонт квартир в 2026...",
"modtime": "20170827T120000",
"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 можно передать в DELETE /v1/search/yandex/cache/{batchId}, чтобы сбросить всё, что этот пакет положил в кэш.

Собственный формат отдаёт всё, что присылает Яндекс, — совместимые форматы этого не умеют, потому что в их схемах просто нет таких полей.

Поле Что это
pos Абсолютная позиция в выдаче. Не индекс в массиве: результаты склеиваются из страниц, фильтруются по доменам и пересобираются, поэтому позиция едет отдельно
doc_id Идентификатор документа у Яндекса — единственный способ узнать одну и ту же страницу в разных запросах
domain Домен как его прислал Яндекс
snippet / passages Сниппет и дополнительные пассажи, если они отличаются от сниппета
modtime Когда документ менялся — сигнал свежести
lang Язык документа. Именно документа, а не запроса
size / mime_type / charset Отличить страницу на 9 КБ от PDF на 40 МБ до того, как её качать
saved_copy_url Сохранённая копия у Яндекса. Ссылка подписанная и живёт по расписанию Яндекса, а не нашему

Блок meta описывает саму выдачу: found — сколько всего документов нашёл Яндекс (сигнал конкурентности), reqid — идентификатор для обращения в поддержку, is_local — что выдача была локализована, effective_request — что Яндекс на самом деле применил, если это отличается от запрошенного.

status у каждого запроса:

Статус Что значит
queued Принят, ещё не отправлен в Яндекс
pending Отправлен, ответа пока нет
done Результаты готовы
error Яндекс вернул ошибку по этому запросу — остальные не пострадали
expired Не успел за время жизни пакета (12 часов) либо выдача была сброшена из кэша. Не оплачивается

Пакет считается done, когда ни один запрос не остался в работе — это не значит, что все успешны, поэтому смотрите статус по каждому. counts даёт то же самое числом, чтобы не перебирать массив.

Если результаты нужны не сию секунду — отправьте пакет в /async и заберите позже. Это в десять раз дешевле синхронного поиска.

Окно терминала
# 1. Отправляем — ответ приходит сразу, с id
curl -X POST "https://proxy.unoapi.ru/v1/search/yandex/async" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"queries": [{"query": "ремонт квартир"}], "defaults": {"region": 213}}'
# 2. Забираем, когда удобно. Чтение бесплатное
curl "https://proxy.unoapi.ru/v1/search/yandex/async/BATCH_ID" \
-H "Authorization: Bearer YOUR_API_KEY"

Результаты хранятся 12 часов. Забирать можно сколько угодно раз — повторное чтение ничего не стоит и в Яндекс не ходит.

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

Листать глубже помогает offset в Brave-совместимом GET: offset=100 — вторая сотня. Отсчёт идёт в результатах, а не в страницах, поэтому окно может пересечь границу сотни — тогда дозапрашиваются обе страницы и считаются обе ставки.

Страницы Яндекса на глубине перекрываются: две соседние могут содержать одни и те же URL. Мы убираем повторы и пересчитываем позиции, поэтому запрос на 200 возвращает до 200 результатов, а не ровно 200.

Параметр region принимает код региона Яндекса и локализует выдачу. Опустите или передайте 0 — регион определится по IP вызывающего.

  • 225 — Россия
  • 213 — Москва
  • 2 — Санкт-Петербург
  • 65 — Новосибирск

Полный справочник — в документации Яндекса.

Окно терминала
# Совместимый POST — регион в теле
curl -X POST "https://proxy.unoapi.ru/v1/search/yandex" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "доставка пиццы", "max_results": 5, "region": 213}'
# Совместимый GET — регион в query
curl "https://proxy.unoapi.ru/v1/search/yandex?q=доставка+пиццы&count=5&region=213" \
-H "Authorization: Bearer YOUR_API_KEY"

freshness ограничивает выдачу по времени: pd — сутки, pw — неделя, pm — месяц, py — год. Принимается в пакетных запросах и в Brave-совместимом GET. У Tavily-совместимого POST такого поля нет, и лишнее поле в теле не игнорируется, а отклоняется: придёт 422 с unexpected property.

Учтите: запрос со свежестью — это другой поисковый запрос, а не фильтр поверх старого. «За последнюю неделю» завтра означает другой интервал, поэтому такие выдачи кэшируются отдельно.

include_domains и exclude_domains применяются при отдаче, а не при запросе в Яндекс. Одна закэшированная выдача обслуживает любые комбинации фильтров, поэтому смена фильтра не стоит новой выборки — это попадание в кэш по ставке 10 ₽ за 1000, а не 600.

Окно терминала
curl -X POST "https://proxy.unoapi.ru/v1/search/yandex" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "новости технологий",
"include_domains": ["habr.com", "vc.ru"],
"max_results": 10
}'

Совпадение идёт по домену и его поддоменам: habr.com включает career.habr.com, но не nothabr.com.

Выдача хранится 24 часа по умолчанию. Управляется параметром cache_ttl в пакетных запросах: до 30 дней, 0 — не брать из кэша и ничего не оставлять после себя.

Исключение — /async: у отложенных результатов нижняя граница хранения 12 часов, потому что забирать их вы будете позже. cache_ttl: 0 там означает «не читать из кэша», но записанное проживёт 12 часов, а не ноль.

cache_ttl — про срок, а не про сброс. Чтобы выкинуть конкретную выдачу:

Окно терминала
# По запросам — тело такое же, как у поиска
curl -X DELETE "https://proxy.unoapi.ru/v1/search/yandex/cache" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"queries": [{"query": "ремонт квартир", "region": 213, "max_results": 200}]}'
# Или всё, что произвёл пакет
curl -X DELETE "https://proxy.unoapi.ru/v1/search/yandex/cache/BATCH_ID" \
-H "Authorization: Bearer YOUR_API_KEY"

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

Drop-in замена Tavily Search API: меняете базовый URL, код остаётся прежним.

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

Drop-in замена Brave Search API.

Окно терминала
curl "https://proxy.unoapi.ru/v1/search/yandex?q=погода+москва&count=10&country=ru" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"type": "search",
"query": { "original": "погода москва" },
"web": {
"results": [
{
"title": "Погода в Москве на сегодня",
"url": "https://example.com/weather/moscow",
"description": "Прогноз погоды в Москве...",
"extra_snippets": ["..."]
}
]
}
}

offset листает выдачу — см. Пагинация и глубина выдачи.

async function searchTool(query: string): Promise<string> {
const res = await fetch('https://proxy.unoapi.ru/v1/search/yandex/smart', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.UNOAPI_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ queries: [{ query, max_results: 5 }] }),
});
const { items } = await res.json();
return (items[0].results ?? [])
.map((r) => `${r.pos}. [${r.title}](${r.url})\n${r.snippet}`)
.join('\n\n');
}

Агент, который переформулирует запрос и пробует несколько вариантов, платит за совпавшие формулировки один раз: одинаковые запросы внутри пакета уходят в Яндекс однажды, повтор считается попаданием в кэш и стоит 1 копейку.

Следующий шаг после выдачи — содержимое найденных страниц. Smart Scrape отдаёт его одним запросом: чистый Markdown или типизированный источник, каскад от кэша и сохранённых копий поисковых систем до headless-браузера — Chromium запускается и оплачивается только когда без него не обойтись.

https://api.tavily.com/search
https://proxy.unoapi.ru/v1/search/yandex
https://api.search.brave.com/res/v1/web/search
https://proxy.unoapi.ru/v1/search/yandex

Меняется только базовый URL и ключ. Умный подбор ставки, кэш и отложенный режим включаются сами.

Язык запроса определяется автоматически. Оптимизировано для кириллицы: 🇷🇺 🇺🇦 🇧🇾 🇰🇿