Документация API

Ниже представлены доступные эндпоинты для получения данных из поисковых систем и Вордстата. Машиночитаемая спека: openapi.json (OpenAPI 3.1).

Содержание


Аутентификация

Все методы API используют один и тот же ключ из личного кабинета. Передать его можно двумя способами: заголовком запроса или параметром key в адресе.

Заголовком запроса:

Authorization: Bearer ВАШ_КЛЮЧ

Параметром key:

https://jsonseo.ru/api/yandex?text=пицца&key=ВАШ_КЛЮЧ

Быстрая проверка через curl:

curl -H "Authorization: Bearer ВАШ_КЛЮЧ" "https://jsonseo.ru/api/yandex?text=пицца"

Параметры-флаги, описанные ниже как 0 или 1, принимают также true и false в любом регистре.


GET и POST

Любой метод API принимает оба глагола. Параметры одни и те же: в GET они едут в адресе, в POST - телом формы (application/x-www-form-urlencoded). Ответ не зависит от выбранного способа.

Один и тот же запрос двумя способами:

curl "https://jsonseo.ru/api/yandex?text=ремонт+айфона&lr=213&key=ВАШ_КЛЮЧ"

curl -X POST "https://jsonseo.ru/api/yandex" \
  -d "key=ВАШ_КЛЮЧ" -d "lr=213" -d "text=ремонт айфона"

Когда нужен POST

Когда параметр длинный. Адресная строка у нас принимается примерно до 65 000 байт. Кириллица в ней занимает втрое больше места, чем в обычном тексте: каждая буква превращается в шесть символов вида %D1%80. Поэтому список русских фраз перестаёт помещаться примерно с 500 штук - точная граница зависит от того, насколько фразы длинные.

Отказ при этом невнятный: кода ошибки не будет, соединение просто оборвётся, и клиент увидит сетевой сбой без тела ответа. Так что если вы отправляете длинные списки - например в /direct, - берите POST сразу, не дожидаясь границы.

У тела предел куда выше - 2 МиБ; на что-то большее метод ответит 413, и это уже внятная ошибка с текстом.

На короткие запросы это не влияет никак: проверка позиции или частотности одной фразы спокойно живёт в адресе.


Коды ответов

У JSON-методов ошибка приходит одинаково: поле message с готовым к показу текстом на русском. Если ошибка привязана к конкретному параметру, добавляется errors; если нет - в теле только message.

{
    "message": "Параметр pages должен быть от 1 до 20.",
    "errors": {
        "pages": ["Параметр pages должен быть от 1 до 20."]
    }
}

XML-методы - исключение. /yandex/xml и /google/xml отдают ошибку не кодом ответа, а телом: HTTP-статус остаётся 200, а внутри лежит <error code="N">текст</error> - так же, как это делают Яндекс XML и агрегаторы. Значит, при 200 нужно смотреть, нет ли в теле <error>. Статус при этом не игнорируйте: ошибка может случиться и раньше, чем метод начнёт работу, - тогда придёт обычный код ответа, а XML в теле не будет вовсе. Номера ошибок - в описании метода.

Код Когда приходит и что делать
200 Успешный запрос, в теле результат.
402 На балансе недостаточно средств. Пополните счёт. Списаний по такому запросу нет.
403 Ключ не передан или недействителен - сверьте его с кабинетом. Тот же код приходит на служебные методы, доступные только нам: их правами обычный ключ не наделить. Повтор не поможет.
404 Такого метода нет - почти всегда опечатка в адресе. Список путей ниже и в openapi.json.
405 Путь существует, но не принимает этот HTTP-метод. Все методы API отвечают на GET и POST - возьмите любой из двух.
413 Тело запроса не прочиталось - обычно потому, что оно больше 2 МиБ; тогда разбейте список на несколько запросов, см. GET и POST. Если тело заведомо меньше лимита, возможен сбой передачи - попробуйте повторить запрос.
422 Не хватает обязательного параметра или значение вне допустимых. Что именно не так - в message; если ошибку удалось привязать к параметру, он назван и в errors. Повтор не поможет, нужно исправить запрос.
429 Упёрлись в один из лимитов: бесплатные методы - 30 запросов в минуту на ключ; прогноз /direct - 100 запросов в час на аккаунт; слишком много ваших запросов ожидает обработки одновременно; наконец, поток запросов с неверными ключами с одного адреса - тогда 429 может достаться и верному ключу, так что проверьте, не ходит ли с того же адреса что-то со старым ключом. В заголовке Retry-After - через сколько секунд имеет смысл вернуться.
502 Сервис в этот момент недоступен - например, идёт обновление. Ответ на такую ошибку может прийти не в JSON. Повторите через несколько секунд.
503 Получить выдачу не вышло: поисковик не ответил либо запрос не удался на нашей стороне. Повторите попытку, обычно повтор проходит. Денег за неудачу не берём; если всё же видите списание по такому запросу - напишите нам, разберёмся вручную.

Коротко о том, что повторять: 429, 502 и 503 имеет смысл повторить - первый не раньше, чем скажет Retry-After. 403, 404, 405 и 422 повторять бессмысленно: их лечит правка запроса. 413 повторять бессмысленно при превышении размера, но при сбое передачи повтор может помочь. 402 лечится пополнением баланса.


Официальные SDK

Клиентские библиотеки для четырёх языков. Выполняют авторизацию, сборку параметров, разбор ответа и повторные попытки.

Язык Установка Требования Исходники
PHP composer require jsonseo/php-sdk PHP 7.1 и новее GitHub, Packagist
Node.js npm install jsonseo Node.js 18 и новее, Bun, Deno GitHub, npm
Python pip install jsonseo Python 3.8 и новее GitHub, PyPI
Go go get github.com/jsonseo/go-sdk Go 1.21 и новее GitHub, pkg.go.dev

Сторонних зависимостей нет. Реализованы все методы, описанные на этой странице, кроме XML. Имена методов соответствуют путям: /wordstat/frequency - wordstatFrequency, wordstat_frequency или WordstatFrequency в зависимости от языка. Настройки клиента, повторные попытки и типы ошибок описаны в README каждой библиотеки.

PHP

$client = new JsonSeo\Client('ВАШ_КЛЮЧ');

$serp = $client->yandex([
    'text' => 'купить ноутбук',
    'region' => 213,
]);

echo $serp['results'][0]['domain'];

Node.js и TypeScript

Пакет собран в ESM и CommonJS, типы включены.

import { JsonSeoClient } from 'jsonseo';

const client = new JsonSeoClient('ВАШ_КЛЮЧ');

const serp = await client.yandex({ text: 'купить ноутбук', region: 213 });

console.log(serp.results[0].domain);

Python

from jsonseo import Client

client = Client("ВАШ_КЛЮЧ")

serp = client.yandex("купить ноутбук", region=213)

print(serp["results"][0]["domain"])

Go

client, err := jsonseo.New("ВАШ_КЛЮЧ")
if err != nil {
    log.Fatal(err)
}

serp, err := client.Yandex(context.Background(), "купить ноутбук", jsonseo.Params{
    "region": 213,
})
if err != nil {
    log.Fatal(err)
}

fmt.Println(serp.Results[0].Domain)

/balance

Текущий баланс аккаунта. Удобно для мониторинга остатка средств из ваших скриптов и интеграций.

Метод:

GET|POST https://jsonseo.ru/api/balance

Стоимость запроса:

Бесплатно

Ключ обязателен: по нему находится аккаунт и считается лимит в 30 запросов в минуту.

Пример запроса:

curl "https://jsonseo.ru/api/balance?key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "balance": 123.45,
    "currency": "RUB"
}

/yandex

Получение поисковой выдачи из Яндекс.

Метод:

GET|POST https://jsonseo.ru/api/yandex

Параметры запроса:

Стоимость запроса:

0.01₽ × количество страниц

Указывается максимальное количество страниц, которое нужно получить. Если поиск вернёт меньше страниц, чем вы запросили, списание произойдёт только за фактически полученные страницы. При ai=1 прибавляется ещё 0.01 ₽ - и только если ответ Алисы пришёл.

Пример запроса:

curl
curl "https://jsonseo.ru/api/yandex?text=купить+ноутбук&region=213&key=ВАШ_КЛЮЧ"
PHP
<?php

$params = http_build_query([
    'key' => 'ВАШ_КЛЮЧ',
    'text' => 'купить ноутбук',
    'region' => 213,
]);

$response = file_get_contents('https://jsonseo.ru/api/yandex?' . $params);
$data = json_decode($response, true);

foreach ($data['results'] as $index => $item) {
    echo ($index + 1) . '. ' . $item['url'] . PHP_EOL;
}
Python
import requests

response = requests.get(
    'https://jsonseo.ru/api/yandex',
    params={'text': 'купить ноутбук', 'region': 213},
    headers={'Authorization': 'Bearer ВАШ_КЛЮЧ'},
)
response.raise_for_status()

for index, item in enumerate(response.json()['results'], start=1):
    print(index, item['url'])
JavaScript
const params = new URLSearchParams({text: 'купить ноутбук', region: 213});

const response = await fetch(`https://jsonseo.ru/api/yandex?${params}`, {
    headers: {Authorization: 'Bearer ВАШ_КЛЮЧ'},
});

const data = await response.json();
data.results.forEach((item, index) => console.log(index + 1, item.url));

Пример ответа:


{
    "pages": 1,
    "exhausted": false,
    "breakDomainHit": false,
    "found": 116000000,
    "found_human": "нашлось 116 млн результатов",
    "lr": 213,
    "query": "купить ноутбук",
    "rawQuery": "купть ноутбук",
    "results": [
        {
            "url": "https://www.VZON.ru/category/noutbuki-15692/",
            "domain": "www.vzon.ru",
            "title": "Ноутбуки: купить ноутбук на VZON по низкой цене",
            "passage": "Покупайте ноутбуки на VZON по выгодным ценам, быстрая и бесплатная доставка...",
            "breadcrumbs": "vzon.ru›Электроника›Ноутбуки, планшеты и электронные книги"
        }
    ]
}

Поля ответа:


/yandex/xml

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

Этот эндпоинт предназначен для интеграции в приложения и может использоваться вместо сервисов XMLRiver, XMLStock, XMLProxy, XMLSeo. Готовый URL для запросов доступен в личном кабинете.

Метод:

GET|POST https://jsonseo.ru/api/yandex/xml

Готовая ссылка:

https://jsonseo.ru/api/yandex/xml?key=ВАШ_КЛЮЧ

Параметры запроса:

Оплачивается только запрошенная страница: при page=1 и groupby=100 списывается за 10 страниц выдачи, а не за 20. Максимальная глубина - 20 страниц (200 результатов): потолок общий на page и groupby, поэтому при groupby=100 доступны две страницы: 0 и 1.
Все позиции сразу получают через groupby при page=0 - см. смещение выдачи.

Стоимость запроса:

0.01₽ × количество страниц

Количество страниц = количество позиций ÷ 10, независимо от page. Например: 100 позиций - 10 страниц - 0.1 ₽; при page=1 те же 100 позиций стоят те же 0.1 ₽, оплачивается только запрошенная страница.

Пример ответа:

<?xml version="1.0" encoding="utf-8"?>
<yandexsearch version="1.0">
    <response date="20260504T120000" dateiso="2026-05-04T12:00:00Z">
        <reqid>1746345600123456-1234567890123456789</reqid>
        <found priority="phrase">128929</found>
        <found priority="strict">128929</found>
        <found priority="all">128929</found>
        <found-human>нашлось 128 тыс. результатов</found-human>
        <misspell>
            <rule>Misspell</rule>
            <source-text>кпить ноутбук</source-text>
            <text>купить ноутбук</text>
        </misspell>
        <results>
            <grouping attr="" mode="flat" groups-on-page="10" docs-in-group="1">
                <page first="1" last="10">0</page>
                <group>
                    <doccount>1</doccount>
                    <doc id="ZC2633C719742EBE4">
                        <url>https://www.example.com/category/noutbuki/</url>
                        <domain>www.example.com</domain>
                        <title>Ноутбуки: купить ноутбук по низкой цене</title>
                        <breadcrumbs/>
                        <mime-type>application/pdf</mime-type>
                        <passages>
                            <passage>Покупайте ноутбуки по выгодным ценам, быстрая и бесплатная доставка...</passage>
                        </passages>
                        <contenttype>organic</contenttype>
                    </doc>
                </group>
            </grouping>
        </results>
    </response>
</yandexsearch>
Тег <mime-type> появляется только у документов (pdf, doc, xls и т.д.); у обычных страниц его нет. Блок <misspell> - только когда Яндекс сам исправил запрос и искал по исправленному: <source-text> - что прислали вы, <text> - по чему искали. При hlword=1 исправленные слова в <source-text> выделяются.

Коды ошибок:

Ошибка возвращается XML-ом с кодом ответа 200 - так же, как это делают Яндекс XML и агрегаторы: <error code="N">текст</error>. Номера совпадают с Яндекс XML.


/yandex/suggest

Поисковые подсказки Яндекса (саджест): фразы, которые Яндекс предлагает при вводе запроса. Подсказки собираются без персонализации и истории - только «чистый» список запросов, с учётом региона. Источник идей для расширения семантики и анализа спроса.

Метод:

GET|POST https://jsonseo.ru/api/yandex/suggest

Параметры запроса:

Стоимость запроса:

0.01₽ за запрос

Пагинации нет - все подсказки (до 50) приходят за один запрос.

Пример запроса:

curl
curl "https://jsonseo.ru/api/yandex/suggest?text=купить+квартиру&region=213&key=ВАШ_КЛЮЧ"
PHP
<?php

$params = http_build_query([
    'key' => 'ВАШ_КЛЮЧ',
    'text' => 'купить квартиру',
    'region' => 213,
]);

$response = file_get_contents('https://jsonseo.ru/api/yandex/suggest?' . $params);
$data = json_decode($response, true);

foreach ($data['results'] as $suggestion) {
    echo $suggestion . PHP_EOL;
}
Python
import requests

response = requests.get(
    'https://jsonseo.ru/api/yandex/suggest',
    params={'text': 'купить квартиру', 'region': 213},
    headers={'Authorization': 'Bearer ВАШ_КЛЮЧ'},
)
response.raise_for_status()

for suggestion in response.json()['results']:
    print(suggestion)
JavaScript
const params = new URLSearchParams({text: 'купить квартиру', region: 213});

const response = await fetch(`https://jsonseo.ru/api/yandex/suggest?${params}`, {
    headers: {Authorization: 'Bearer ВАШ_КЛЮЧ'},
});

const data = await response.json();
data.results.forEach(suggestion => console.log(suggestion));

Пример ответа:


{
    "query": "купить квартиру",
    "results": [
        "купить квартиру в москве",
        "купить квартиру в новостройке",
        "купить квартиру в подмосковье",
        "купить квартиру вторичка",
        "купить квартиру от застройщика"
    ],
    "lr": "213"
}

Поля ответа:


/yandex/regions

Справочник регионов Яндекса: поиск кода региона (lr) по названию города или области. Метод бесплатный, но ключ нужен: по нему считается лимит в 30 запросов в минуту. Тот же справочник доступен на странице регионов Яндекса.

Метод:

GET|POST https://jsonseo.ru/api/yandex/regions

Параметры запроса:

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

Стоимость запроса:

Бесплатно

Пример запроса:

curl "https://jsonseo.ru/api/yandex/regions?name=Казань&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "name": "Казань",
    "lang": "ru",
    "regions": [
        {
            "id": 43,
            "name": "Казань",
            "subname": "Республика Татарстан",
            "lat": 55.796129,
            "lon": 49.106414
        }
    ]
}
id подставляется в параметр region (он же lr) методов /yandex, /yandex/xml, /yandex/suggest и /wordstat. Координаты lat и lon пригодятся для геолокации в /bing.

/yandex/images

Поиск по картинкам в Яндексе.

Метод:

GET|POST https://jsonseo.ru/api/yandex/images

Параметры запроса:

Общие для трёх поисковиков - см. параметры поиска по картинкам. Там же описаны фильтры и формат ответа. Ниже - только то, что своё у этого метода.

Своё у Яндекса:

Результатов на странице:

20

Стоимость запроса:

0.01₽ × количество страниц

Списание идёт за фактически полученные страницы: если выдача закончилась раньше запрошенного pages, платить за ненайденное не придётся.

Пример запроса:

curl "https://jsonseo.ru/api/yandex/images?text=котики&size=large&format=jpg&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "pages": 1,
    "exhausted": false,
    "query": "котики",
    "lr": 213,
    "results": [
        {
            "url": "https://i.ytimg.com/vi/Fdier2UCgo0/maxresdefault.jpg",
            "title": "Cats Try Not To Laugh 17 - YouTube",
            "domain": "youtube.com",
            "sourceUrl": "https://www.youtube.com/watch?v=Fdier2UCgo0",
            "thumbnail": "https://avatars.mds.yandex.net/i?id=a5d639a87b2590663763dbdc42ee0367",
            "width": 1280,
            "height": 720,
            "thumbnailWidth": 480,
            "thumbnailHeight": 270,
            "bytes": 78219
        }
    ]
}

/yandex/video

Поиск по видео в Яндексе.

Метод:

GET|POST https://jsonseo.ru/api/yandex/video

Параметры запроса:

Общие для трёх поисковиков - см. параметры поиска по видео. Там же описаны фильтры и формат ответа. Ниже - только то, что своё у этого метода.

Своё у Яндекса:

Результатов на странице:

до 20. Часть позиций страницы занимает реклама - она в результаты не попадает, поэтому обычно приходит 16-20 роликов

Стоимость запроса:

0.01₽ × количество страниц

Списание идёт за фактически полученные страницы: если выдача закончилась раньше запрошенного pages, платить за ненайденное не придётся.

Пример запроса:

curl "https://jsonseo.ru/api/yandex/video?text=как+помыть+кота&duration=short&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "pages": 1,
    "exhausted": false,
    "query": "как помыть кота",
    "lr": 213,
    "results": [
        {
            "url": "http://vk.com/video-192188557_456286524",
            "title": "Забавные костюмы для котиков — Видео от Опасная Земля",
            "domain": "vk.com",
            "thumbnail": "https://avatars.mds.yandex.net/get-video_thumb_fresh/877004/564x318_1",
            "duration": 65,
            "durationText": "1:05",
            "published": 1788671516,
            "views": "1,5K",
            "provider": "VK Видео",
            "description": "Забавные костюмы на Хэллуин для котиков..."
        }
    ]
}

/google

Получение поисковой выдачи из Google (мобильная выдача google.com).

Метод:

GET|POST https://jsonseo.ru/api/google

Параметры запроса:

Стоимость запроса:

0.01₽ × количество страниц

Указывается максимальное количество страниц, которое нужно получить. Если поиск вернёт меньше страниц, чем вы запросили, списание произойдёт только за фактически полученные страницы. При ai=1 прибавляется ещё 0.01 ₽ - и только если AI Overview пришёл.

Пример запроса:

curl
curl "https://jsonseo.ru/api/google?q=купить+ноутбук&region=1011969&key=ВАШ_КЛЮЧ"
PHP
<?php

$params = http_build_query([
    'key' => 'ВАШ_КЛЮЧ',
    'q' => 'купить ноутбук',
    'region' => 1011969,
]);

$response = file_get_contents('https://jsonseo.ru/api/google?' . $params);
$data = json_decode($response, true);

foreach ($data['results'] as $index => $item) {
    echo ($index + 1) . '. ' . $item['url'] . PHP_EOL;
}
Python
import requests

response = requests.get(
    'https://jsonseo.ru/api/google',
    params={'q': 'купить ноутбук', 'region': 1011969},
    headers={'Authorization': 'Bearer ВАШ_КЛЮЧ'},
)
response.raise_for_status()

for index, item in enumerate(response.json()['results'], start=1):
    print(index, item['url'])
JavaScript
const params = new URLSearchParams({q: 'купить ноутбук', region: 1011969});

const response = await fetch(`https://jsonseo.ru/api/google?${params}`, {
    headers: {Authorization: 'Bearer ВАШ_КЛЮЧ'},
});

const data = await response.json();
data.results.forEach((item, index) => console.log(index + 1, item.url));

Пример ответа:


{
    "pages": 1,
    "exhausted": false,
    "breakDomainHit": false,
    "query": "купить ноутбук",
    "rawQuery": "купть ноутбук",
    "region": "Москва, Россия",
    "url": "https://www.google.com/search?q=...",
    "results": [
        {
            "url": "https://www.example.com/category/noutbuki/",
            "domain": "www.example.com",
            "title": "Ноутбуки: купить ноутбук по низкой цене",
            "passage": "Покупайте ноутбуки по выгодным ценам, быстрая и бесплатная доставка...",
            "breadcrumbs": "example.com › Электроника › Ноутбуки"
        }
    ]
}

Поля ответа:


/google/xml

Получение поисковой выдачи Google в формате XML.

Ответ имеет ту же структуру, что и /yandex/xml, поэтому эндпоинт подходит программам, которые умеют работать с Яндекс XML (Key Collector, TopSite и другие), и может использоваться вместо сервисов XMLRiver, XMLStock, XMLProxy, XMLSeo. Готовый URL для запросов доступен в личном кабинете.

Метод:

GET|POST https://jsonseo.ru/api/google/xml

Готовая ссылка:

https://jsonseo.ru/api/google/xml?key=ВАШ_КЛЮЧ

Параметры запроса:

Оплачивается только запрошенная страница: при page=1 и groupby=100 списывается за 10 страниц выдачи, а не за 20. Максимальная глубина - 20 страниц (200 результатов): потолок общий на page и groupby, поэтому при groupby=100 доступны две страницы: 0 и 1.
Все позиции сразу получают через groupby при page=0 - см. смещение выдачи.

Параметры XMLRiver и XMLStock:

Адрес можно вставить в программу, настроенную на эти сервисы, — их имена параметров мы понимаем:

Работают только на этом адресе: в JSON у нас есть свои gl, region и zone, и второго имени тому же самому там нет. Свои параметры всегда сильнее: если задан и gl, и country, берётся gl.

Стоимость запроса:

0.01₽ × количество страниц

Количество страниц = количество позиций ÷ 10, независимо от page. Например: 100 позиций - 10 страниц - 0.1 ₽; при page=1 те же 100 позиций стоят те же 0.1 ₽, оплачивается только запрошенная страница.

Пример ответа:

<?xml version="1.0" encoding="utf-8"?>
<yandexsearch version="1.0">
    <response date="20260504T120000" dateiso="2026-05-04T12:00:00Z">
        <found priority="phrase">100</found>
        <found priority="strict">100</found>
        <found priority="all">100</found>
        <misspell>
            <rule>Misspell</rule>
            <source-text>recieve payment</source-text>
            <text>receive payment</text>
        </misspell>
        <results>
            <grouping attr="" mode="flat" groups-on-page="10" docs-in-group="1">
                <page first="1" last="10">0</page>
                <group>
                    <doccount>1</doccount>
                    <doc id="ZC2633C719742EBE4">
                        <url>https://www.example.com/category/noutbuki/</url>
                        <domain>www.example.com</domain>
                        <title>Ноутбуки: купить ноутбук по низкой цене</title>
                        <breadcrumbs>example.com › Электроника › Ноутбуки</breadcrumbs>
                        <mime-type>application/pdf</mime-type>
                        <passages>
                            <passage>Покупайте ноутбуки по выгодным ценам, быстрая и бесплатная доставка...</passage>
                        </passages>
                        <contenttype>organic</contenttype>
                    </doc>
                </group>
            </grouping>
        </results>
    </response>
</yandexsearch>

/google/suggest

Поисковые подсказки Google (autocomplete): фразы, которые Google предлагает при вводе запроса. Подсказки собираются без персонализации - «чистый» список запросов с учётом региона. Источник идей для расширения семантики и анализа спроса.

Метод:

GET|POST https://jsonseo.ru/api/google/suggest

Параметры запроса:

Стоимость запроса:

0.01₽ за запрос

Пагинации нет - все подсказки (до ~15) приходят за один запрос.

Пример запроса:

curl
curl "https://jsonseo.ru/api/google/suggest?q=купить+ноутбук&region=1011969&key=ВАШ_КЛЮЧ"
PHP
<?php

$params = http_build_query([
    'key' => 'ВАШ_КЛЮЧ',
    'q' => 'купить ноутбук',
    'region' => 1011969,
]);

$response = file_get_contents('https://jsonseo.ru/api/google/suggest?' . $params);
$data = json_decode($response, true);

foreach ($data['results'] as $suggestion) {
    echo $suggestion . PHP_EOL;
}
Python
import requests

response = requests.get(
    'https://jsonseo.ru/api/google/suggest',
    params={'q': 'купить ноутбук', 'region': 1011969},
    headers={'Authorization': 'Bearer ВАШ_КЛЮЧ'},
)
response.raise_for_status()

for suggestion in response.json()['results']:
    print(suggestion)
JavaScript
const params = new URLSearchParams({q: 'купить ноутбук', region: 1011969});

const response = await fetch(`https://jsonseo.ru/api/google/suggest?${params}`, {
    headers: {Authorization: 'Bearer ВАШ_КЛЮЧ'},
});

const data = await response.json();
data.results.forEach(suggestion => console.log(suggestion));

Пример ответа:


{
    "query": "купить ноутбук",
    "results": [
        "купить ноутбук игровой",
        "купить ноутбук бу",
        "купить ноутбук недорого",
        "купить ноутбук apple",
        "купить ноутбук в москве"
    ]
}

Поля ответа:


/google/regions

Справочник регионов Google: поиск числового ID региона по названию города или страны. Вместе с ID возвращается готовый параметр uule, который можно подставить прямо в адрес выдачи Google. Метод бесплатный, но ключ нужен: по нему считается лимит в 30 запросов в минуту. Те же данные есть на страницах регионов Google и генератора UULE.

Метод:

GET|POST https://jsonseo.ru/api/google/regions

Параметры запроса:

Возвращаются самые популярные совпадения, не больше 30 за запрос: короткий запрос вроде «ново» совпадает с тысячами названий. Уточните название, если нужного региона нет в ответе.

Стоимость запроса:

Бесплатно

Пример запроса:

curl "https://jsonseo.ru/api/google/regions?name=Казань&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "name": "Казань",
    "lang": "ru",
    "regions": [
        {
            "id": 1012054,
            "name": "Казань",
            "subname": "Республика Татарстан, Россия",
            "type": "city",
            "type_name": "город",
            "canonical_name": "Kazan,Republic of Tatarstan,Russia",
            "uule": "w+CAIQICIiS2F6YW4sUmVwdWJsaWMgb2YgVGF0YXJzdGFuLFJ1c3NpYQ",
            "lat": 55.7878944,
            "lon": 49.1233293
        }
    ]
}
id подставляется в параметр region методов /google и /google/xml: сервер сам соберёт UULE и подставит страну. uule нужен, только если вы обращаетесь к Google напрямую. canonical_name всегда английское: именно из него собирается UULE. Параметр lang меняет только name и subname.

/google/images

Поиск по картинкам в Google.

Метод:

GET|POST https://jsonseo.ru/api/google/images

Параметры запроса:

Общие для трёх поисковиков - см. параметры поиска по картинкам. Там же описаны фильтры и формат ответа. Ниже - только то, что своё у этого метода.

Своё у Google:

Результатов на странице:

100 - впятеро больше, чем у Яндекса, за ту же цену страницы

Стоимость запроса:

0.01₽ × количество страниц

Списание идёт за фактически полученные страницы: если выдача закончилась раньше запрошенного pages, платить за ненайденное не придётся.

Пример запроса:

curl "https://jsonseo.ru/api/google/images?q=котики&size=large&format=png&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "pages": 1,
    "exhausted": false,
    "query": "котики",
    "results": [
        {
            "url": "https://www.kha.com/wp-content/uploads/2019/11/cats.webp",
            "title": "Котики - фотографии и картинки",
            "domain": "www.kha.com",
            "sourceUrl": "https://www.kha.com/cats/",
            "thumbnail": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...",
            "width": 574,
            "height": 720
        }
    ]
}

/google/video

Поиск по видео в Google.

Метод:

GET|POST https://jsonseo.ru/api/google/video

Параметры запроса:

Общие для трёх поисковиков - см. параметры поиска по видео. Там же описаны фильтры и формат ответа. Ниже - только то, что своё у этого метода.

Своё у Google:

Результатов на странице:

10

Стоимость запроса:

0.01₽ × количество страниц

Списание идёт за фактически полученные страницы: если выдача закончилась раньше запрошенного pages, платить за ненайденное не придётся.

Пример запроса:

curl "https://jsonseo.ru/api/google/video?q=как+помыть+кота&duration=long&freshness=year&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "pages": 1,
    "exhausted": false,
    "query": "как помыть кота",
    "results": [
        {
            "url": "https://www.youtube.com/watch?v=n0csRIDZegA",
            "title": "Как помыть кота, груминг кошек дома - YouTube",
            "domain": "www.youtube.com",
            "duration": 1878,
            "durationText": "31:18",
            "publishedText": "7 дек. 2020 г.",
            "breadcrumbs": "www.youtube.com › watch"
        }
    ]
}

/bing

Получение поисковой выдачи из Bing (bing.com). Тарификация постраничная: одна страница - 0.01 ₽ независимо от числа результатов в ней.

Метод:

GET|POST https://jsonseo.ru/api/bing

Параметры запроса:

Локация: mkt задаёт страну выдачи и перебивает cc; cc уточняет страну внутри регионального рынка; setlang меняет язык интерфейса, но не состав выдачи. Разбор с замерами - страны, рынки и языки в Bing. Без этих параметров регион определяет сам Bing.

Стоимость запроса:

0.01₽ × количество страниц

Указывается максимальное количество страниц, которое нужно получить. Если поиск вернёт меньше страниц, чем вы запросили, списание произойдёт только за фактически полученные страницы. При ai=1 прибавляется ещё 0.01 ₽ - и только если ответ Copilot пришёл.

Пример запроса:

curl
curl "https://jsonseo.ru/api/bing?q=пицца&ll=55.753930,37.620795&key=ВАШ_КЛЮЧ"
PHP
<?php

$params = http_build_query([
    'key' => 'ВАШ_КЛЮЧ',
    'q' => 'пицца',
    'll' => '55.753930,37.620795',
]);

$response = file_get_contents('https://jsonseo.ru/api/bing?' . $params);
$data = json_decode($response, true);

foreach ($data['results'] as $index => $item) {
    echo ($index + 1) . '. ' . $item['url'] . PHP_EOL;
}
Python
import requests

response = requests.get(
    'https://jsonseo.ru/api/bing',
    params={'q': 'пицца', 'll': '55.753930,37.620795'},
    headers={'Authorization': 'Bearer ВАШ_КЛЮЧ'},
)
response.raise_for_status()

for index, item in enumerate(response.json()['results'], start=1):
    print(index, item['url'])
JavaScript
const params = new URLSearchParams({q: 'пицца', ll: '55.753930,37.620795'});

const response = await fetch(`https://jsonseo.ru/api/bing?${params}`, {
    headers: {Authorization: 'Bearer ВАШ_КЛЮЧ'},
});

const data = await response.json();
data.results.forEach((item, index) => console.log(index + 1, item.url));

Пример ответа:


{
    "pages": 1,
    "exhausted": false,
    "breakDomainHit": false,
    "query": "пицца",
    "rawQuery": "пицца",
    "region": "Москва, Москва",
    "url": "https://www.bing.com/search?q=...",
    "results": [
        {
            "url": "https://lolo-pizza.ru/",
            "domain": "lolo-pizza.ru",
            "title": "Лоло Пицца: кушай и ржи",
            "passage": "Заказать горячую и ржачную пиццу с доставкой за 30 минут...",
            "breadcrumbs": "https://lolo-pizza.ru"
        }
    ]
}

Поля ответа:


/bing/suggest

Поисковые подсказки Bing (autocomplete): фразы, которые Bing предлагает при вводе запроса. Источник идей для расширения семантики и анализа спроса.

Метод:

GET|POST https://jsonseo.ru/api/bing/suggest

Параметры запроса:

Стоимость запроса:

0.01₽ за запрос

Пагинации нет - все подсказки приходят за один запрос.

Пример запроса:

curl "https://jsonseo.ru/api/bing/suggest?q=купить+ноутбук&ll=55.753930,37.620795&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "query": "купить ноутбук",
    "results": [
        "купить ноутбук игровой",
        "купить ноутбук бу",
        "купить ноутбук недорого"
    ]
}

Поля ответа:


/bing/images

Поиск по картинкам в Bing.

Метод:

GET|POST https://jsonseo.ru/api/bing/images

Параметры запроса:

Общие для трёх поисковиков - см. параметры поиска по картинкам. Там же описаны фильтры и формат ответа. Ниже - только то, что своё у этого метода.

Своё у Bing:

Результатов на странице:

до 35, сколько просить - задаёт count

Стоимость запроса:

0.01₽ × количество страниц

Списание идёт за фактически полученные страницы: если выдача закончилась раньше запрошенного pages, платить за ненайденное не придётся.

Пример запроса:

curl "https://jsonseo.ru/api/bing/images?q=кофе&color=mono&count=35&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "pages": 1,
    "exhausted": false,
    "query": "кофе",
    "rawQuery": "кофе",
    "mkt": "ru-RU",
    "results": [
        {
            "url": "https://www.torrefacto.ru/upload/medialibrary/coffee.png",
            "title": "Норма кофеина в день: сколько можно выпить кофе без вреда",
            "domain": "www.torrefacto.ru",
            "sourceUrl": "https://www.torrefacto.ru/blog/daily-dose-of-caffeine/",
            "thumbnail": "https://ts4.mm.bing.net/th?id=OIP.Kkuwq5ACPcMD",
            "width": 1200,
            "height": 750
        }
    ]
}

/bing/video

Поиск по видео в Bing.

Метод:

GET|POST https://jsonseo.ru/api/bing/video

Параметры запроса:

Общие для трёх поисковиков - см. параметры поиска по видео. Там же описаны фильтры и формат ответа. Ниже - только то, что своё у этого метода.

Своё у Bing:

Результатов на странице:

до 105 - больше, чем у Яндекса и Google, и всё за одну страницу. Сколько просить, задаёт count

Стоимость запроса:

0.01₽ × количество страниц

Списание идёт за фактически полученные страницы: если выдача закончилась раньше запрошенного pages, платить за ненайденное не придётся.

Пример запроса:

curl "https://jsonseo.ru/api/bing/video?q=кофе&count=100&site=youtube.com&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "pages": 1,
    "exhausted": false,
    "query": "кофе",
    "rawQuery": "кофе",
    "mkt": "ru-RU",
    "results": [
        {
            "url": "https://www.youtube.com/watch?v=I-FXfanXIl0",
            "title": "Всё, что вы никогда не знали о кофе",
            "domain": "www.youtube.com",
            "thumbnail": "https://ts4.mm.bing.net/th?id=OVP.QaYgEkiikDUS2ew6WCxbUg",
            "duration": 1041,
            "durationText": "17:21",
            "publishedText": "1 месяц назад",
            "views": "Просмотров: 194,9тыс.",
            "provider": "YouTube",
            "channel": "Атлас еды"
        }
    ]
}

/wordstat

Списки популярных и похожих запросов из Яндекс Вордстата - материал для расширения семантики. Частота самой фразы - отдельным методом /wordstat/frequency.

Метод:

GET|POST https://jsonseo.ru/api/wordstat

Параметры запроса:

Стоимость запроса:

0.01₽ за запрос

Фиксированная цена за запрос. Вордстат отдаёт полные списки популярных и похожих запросов сразу, пагинации нет - параметр pages больше не используется.

Пример запроса:

curl
curl "https://jsonseo.ru/api/wordstat?text=ремонт+айфона&region=213&key=ВАШ_КЛЮЧ"
PHP
<?php

$params = http_build_query([
    'key' => 'ВАШ_КЛЮЧ',
    'text' => 'ремонт айфона',
    'region' => 213,
]);

$response = file_get_contents('https://jsonseo.ru/api/wordstat?' . $params);
$data = json_decode($response, true);

foreach ($data['results']['popular'] as $item) {
    echo $item['text'] . ': ' . $item['value'] . PHP_EOL;
}
Python
import requests

response = requests.get(
    'https://jsonseo.ru/api/wordstat',
    params={'text': 'ремонт айфона', 'region': 213},
    headers={'Authorization': 'Bearer ВАШ_КЛЮЧ'},
)
response.raise_for_status()

for item in response.json()['results']['popular']:
    print(item['text'], item['value'])
JavaScript
const params = new URLSearchParams({text: 'ремонт айфона', region: 213});

const response = await fetch(`https://jsonseo.ru/api/wordstat?${params}`, {
    headers: {Authorization: 'Bearer ВАШ_КЛЮЧ'},
});

const {results} = await response.json();
results.popular.forEach((item) => console.log(item.text, item.value));

Пример ответа:


{
    "text": "ремонт айфона",
    "region": "213",
    "device": "desktop,phone,tablet",
    "results": {
        "popular": [
            {
                "text": "ремонт айфонов",
                "value": 128927
            },
            {
                "text": "сколько ремонт айфона",
                "value": 8365
            }
        ],
        "associations": [
            {
                "text": "починить телефон",
                "value": 30546
            }
        ]
    }
}
При ошибке в синтаксисе операторов фразы - статус 200, popular и associations пустые, описание ошибки в поле error. Запрос оплачивается.

/wordstat/frequency

Частота запроса из Вордстата одним числом. Вид частотности задаётся параметром kind - операторы расставляются автоматически, фразу передавайте без кавычек.

Метод:

GET|POST https://jsonseo.ru/api/wordstat/frequency

Параметры запроса:

Те же, что у /wordstat: text*, kind, region, device.

Стоимость запроса:

0.01₽ за запрос

Пример запроса:

curl "https://jsonseo.ru/api/wordstat/frequency?text=ремонт+айфона&kind=exact&region=213&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "text": "\"!ремонт !айфона\"",
    "region": "213",
    "device": "desktop,phone,tablet",
    "results": {
        "totalValue": 27356
    }
}
При ошибке в синтаксисе операторов фразы - статус 200, totalValue равен 0, описание ошибки в поле error. Запрос оплачивается.
В text возвращается фраза, как она ушла в Вордстат - с операторами, подставленными по kind. Снять четыре вида частотности по всему ядру - четыре вызова на фразу, по 0.01 ₽ каждый; какой вид когда нужен - в статье про виды частотности.

/wordstat/graph

Динамика показов запроса: по месяцам и неделям - история с 2018 года, по дням - последние 60 дней. Подходит для оценки сезонности и тренда спроса.

Метод:

GET|POST https://jsonseo.ru/api/wordstat/graph

Параметры запроса:

Стоимость запроса:

0.01₽ за запрос

Пример запроса:

curl "https://jsonseo.ru/api/wordstat/graph?text=купить+ёлку&graph_type=month&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "text": "купить ёлку",
    "region": "all",
    "device": "desktop,phone,tablet",
    "type": "month",
    "results": {
        "graph": [
            {
                "date": "2026-06-01",
                "text": "июнь 2026",
                "absolute": 9042,
                "relative": 0.0001
            },
            {
                "date": "2026-07-01",
                "text": "июль 2026",
                "absolute": 11780,
                "relative": 0.0001
            }
        ]
    }
}
absolute - показы за период, relative - доля показов запроса среди всех показов Яндекса за тот же период (удобно сравнивать сезонность без влияния роста самого поиска).
При ошибке в синтаксисе операторов фразы - статус 200, graph пустой, описание ошибки в поле error. Запрос оплачивается.

/wordstat/map

Распределение показов запроса по регионам и городам России. Параметр region здесь не применяется: метод сам раскладывает спрос по всем регионам.

Метод:

GET|POST https://jsonseo.ru/api/wordstat/map

Параметры запроса:

Стоимость запроса:

0.01₽ за запрос

Пример запроса:

curl "https://jsonseo.ru/api/wordstat/map?text=купить+ноутбук&map_type=regions&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "text": "купить ноутбук",
    "device": "desktop,phone,tablet",
    "type": "regions",
    "results": {
        "rows": [
            {
                "type": "regions",
                "text": "Москва и область",
                "absolute": 111666,
                "popularity": 117.07,
                "relative": 0.005483,
                "region_id": 1
            },
            {
                "type": "regions",
                "text": "Центр",
                "absolute": 178801,
                "popularity": 108.69,
                "relative": 0.00509,
                "region_id": null
            }
        ]
    }
}
absolute - показы из региона за период, popularity - региональная популярность (affinity-индекс: 100 - средний интерес по стране, выше - повышенный), relative - доля запроса среди всех показов региона. region_id - ID региона Яндекса из справочника: его можно сразу передавать в параметр region других методов. null - когда название неоднозначно (в стране одиннадцать «Дзержинских районов») или это сводный макрорегион Вордстата вроде «Центра».
При ошибке в синтаксисе операторов фразы - статус 200, rows пустой, описание ошибки в поле error. Запрос оплачивается.

/direct

Прогноз показов Яндекс Директа по списку ключевых фраз: сколько раз объявление будет показано за выбранный период, со ставками и бюджетом по местам в аукционе. Рекламный кабинет для этого не нужен.

Метод рассчитан на списки: фразы передаются одним запросом, а разбивка на пачки, чистка дублей и сборка ответа - на нашей стороне.

Метод:

GET|POST https://jsonseo.ru/api/direct

Параметры запроса:

Стоимость запроса:

0.01₽ за пачку фраз до 4000 символов

Считается по пачкам, а не по фразам: около 150 обычных фраз укладываются в одну пачку и стоят те же 0.01 ₽, что и запрос на одну фразу. Списывается столько пачек, сколько реально обработано - их число в поле processed. Запросов не больше 100 в час на аккаунт: считаются именно запросы, а не фразы, которых в один помещается до 1000, - то есть при работе списками это 100 000 фраз в час. Собирайте список заранее и отправляйте его методом POST: при отправке по одной фразе лимит исчерпывается на сотне фраз, а длинный список не помещается в адресную строку. Подробнее - в статье про прогноз Директа списком фраз.

Пример запроса:

curl
curl -X POST "https://jsonseo.ru/api/direct" \
  -d "key=ВАШ_КЛЮЧ" \
  -d "region=213" \
  -d "period=month" \
  -d "phrases=ремонт айфона,замена экрана iphone,ремонт телефонов москва"
PHP
<?php

$phrases = ['ремонт айфона', 'замена экрана iphone', 'ремонт телефонов москва'];

$response = file_get_contents('https://jsonseo.ru/api/direct', false, stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
        'content' => http_build_query([
            'key' => 'ВАШ_КЛЮЧ',
            'region' => 213,
            'period' => 'month',
            'phrases' => implode(',', $phrases),
        ]),
    ],
]));

foreach (json_decode($response, true)['results'] as $row) {
    echo $row['phrase'] . ': ' . $row['shows'] . PHP_EOL;
}
Python
import requests

phrases = ['ремонт айфона', 'замена экрана iphone', 'ремонт телефонов москва']

response = requests.post(
    'https://jsonseo.ru/api/direct',
    data={'region': 213, 'period': 'month', 'phrases': ','.join(phrases)},
    headers={'Authorization': 'Bearer ВАШ_КЛЮЧ'},
)
response.raise_for_status()

for row in response.json()['results']:
    print(row['phrase'], row['shows'])
JavaScript
const phrases = ['ремонт айфона', 'замена экрана iphone', 'ремонт телефонов москва'];

const response = await fetch('https://jsonseo.ru/api/direct', {
    method: 'POST',
    headers: {
        Authorization: 'Bearer ВАШ_КЛЮЧ',
        'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams({region: 213, period: 'month', phrases: phrases.join(',')}),
});

const {results} = await response.json();
results.forEach((row) => console.log(row.phrase, row.shows));
Несколько регионов и JSON-тело
curl -X POST "https://jsonseo.ru/api/direct" \
  -H "Authorization: Bearer ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{
        "region": [3, -1],
        "period": "month",
        "phrases": ["ремонт айфона", "замена экрана iphone"]
      }'
Центральный федеральный округ без Москвы и области. В ответе "geo": "3,-1" - для списка это строка, а не число.

Пример ответа:


{
    "geo": 213,
    "period": "month",
    "batches": 1,
    "processed": 1,
    "results": [
        {
            "phrase": "ремонт айфона",
            "shows": 12345,
            "positions": {
                "first_place": {
                    "bid": 145.5,
                    "budget": 4821.3,
                    "clicks": 331,
                    "ctr": 2.68,
                    "shows": 12345
                }
            }
        }
    ],
    "errors": []
}
shows - прогноз показов за период, positions - блоки аукциона: bid и budget в рублях, ctr - в процентах. batches - на сколько пачек разложился список, processed - сколько из них обработано: платите только за обработанные. Если processed меньше batches, прогноз неполный, а не ошибочный: кончился баланс, исчерпано время или часть пачек не удалось получить. errors - сообщения об отклонённых фразах: слово длиннее 35 символов, буквы не из алфавитов Директа, непарные кавычки или одни минус-слова отсеиваются ещё до отправки и не оплачиваются, остальное - словами самого Директа; строк по ним в results не будет, поэтому равенство processed и batches ещё не значит, что прогноз есть по каждой фразе.

/geoip

Определение геолокации по IP-адресу: страна, регион и координаты. ID региона совпадает с ID региона Яндекса: результат можно сразу использовать в параметре region эндпоинтов /yandex и /wordstat.

Метод:

GET|POST https://jsonseo.ru/api/geoip

Аутентификация:

Метод бесплатный, но ключ обязателен: по нему считается лимит в 30 запросов в минуту.

Параметры запроса:

Пример запроса:

curl "https://jsonseo.ru/api/geoip?ip=77.88.55.242&key=ВАШ_КЛЮЧ"

Пример ответа:


{
    "ip": "77.88.55.242",
    "latitude": 55.753215,
    "longitude": 37.622504,
    "region": {
        "id": 213,
        "name": "Москва"
    },
    "country": {
        "id": 225,
        "name": "Россия",
        "iso_name": "RU"
    }
}
Если IP-адрес удалось привязать только к стране, поле region отсутствует, а координаты указывают на центр страны.

AI-ответ (ai=1)

Над выдачей поисковики показывают блок нейросети: текст, собранный по найденным страницам, со ссылками на источники. У Яндекса это «Быстрый ответ Алисы AI», у Google - AI Overview, у Bing - ответ Copilot.

Параметр общий для /yandex, /google и /bing: по умолчанию блок не собирается, включается через ai=1.

curl "https://jsonseo.ru/api/yandex?text=чем+ipv6+отличается+от+ipv4&ai=1&key=ВАШ_КЛЮЧ"
curl "https://jsonseo.ru/api/google?q=чем+ipv6+отличается+от+ipv4&ai=1&key=ВАШ_КЛЮЧ"
curl "https://jsonseo.ru/api/bing?q=чем+ipv6+отличается+от+ipv4&ai=1&key=ВАШ_КЛЮЧ"

Рядом с results появляется aiAnswer - одинаковый у всех трёх:


{
    "pages": 1,
    "results": [ ... ],
    "aiAnswer": {
        "markdown": "IPv6 отличается от IPv4 длиной адреса: 128 бит против 32. [`1`](https://example.ru/ipv6)",
        "sources": [
            {
                "id": 1,
                "url": "https://example.ru/ipv6",
                "domain": "example.ru",
                "title": "Чем IPv6 отличается от IPv4",
                "description": "Разбираем адресацию, заголовок пакета и NAT",
                "citations": 1
            }
        ],
        "followUps": ["Почему IPv6 внедряется так медленно?"]
    }
}

Ответ приходит целиком либо не приходит вовсе.

Цена и время

Цена: +0.01 ₽ к запросу, и только если ответ пришёл. Если у поисковика ответа по запросу нет, поля aiAnswer не будет и запрос обойдётся в обычную цену.

Время: с ai=1 запрос идёт дольше: поисковик генерирует ответ на лету, и это может занять заметное время. Ставьте таймаут HTTP-клиента для запросов с ai=1 не меньше 3 минут - иначе клиент оборвёт запрос, который ещё выполняется. От pages задержка не зависит.

Доступен только с первой страницы. ai=1 вместе со смещением (page, p, start, first) - ошибка 422.

Отдаётся только в JSON. На /yandex/xml и /google/xml параметр ai отклоняется - в схеме Яндекс XML такого блока нет.


Рекламные блоки (ads=1)

Над органикой и под ней поисковики показывают платные объявления. Параметр ads=1 добавляет их в ответ отдельным массивом ads; органика не меняется - реклама в results не подмешивается и позиций не сдвигает.

Работает в /yandex, /google и /yandex/images, по умолчанию выключен. В остальных методах ads=1 возвращает ошибку.

curl "https://jsonseo.ru/api/yandex?text=купить+окна&ads=1&key=ВАШ_КЛЮЧ"
curl "https://jsonseo.ru/api/google?q=купить+окна&ads=1&key=ВАШ_КЛЮЧ"
curl "https://jsonseo.ru/api/yandex/images?text=пластиковые+окна&ads=1&key=ВАШ_КЛЮЧ"

Стоимость:

+0.01₽ за каждую страницу, на которой нашлась реклама

Надбавка резервируется на все запрошенные страницы, а после ответа лишнее возвращается: pages=5&ads=1 спишет 0.10 ₽, и если объявления найдутся на двух страницах, вернётся 0.03 ₽. Несколько объявлений на одной странице - одна надбавка. Если рекламы нет нигде, запрос стоит как обычный.

Время:

С ads=1 запрос идёт дольше: у /yandex немного, у /google заметно, и с ростом pages разница накапливается.

Пример ответа:


{
    "pages": 1,
    "results": [ ... ],
    "ads": [
        {
            "block": "top",
            "position": 1,
            "page": 0,
            "domain": "okna-veka.ru",
            "url": "https://okna-veka.ru/plastikovye-okna/",
            "displayUrl": "okna-veka.ru/пластиковые-окна",
            "title": "Пластиковые окна от производителя — замер бесплатно",
            "description": "Окна VEKA по цене завода. Рассрочка 0%, монтаж за 1 день...",
            "label": "Реклама",
            "format": "text",
            "sitelinks": [
                {"title": "Каталог", "description": "Более 40 моделей в наличии"},
                {"title": "Рассчитать цену"}
            ]
        }
    ]
}

Поля объявления:

Обязательны block, position, page и domain. Остальные поля появляются, только если поисковик их показал. "ads": [] - рекламу просили, но её на странице не было; поля ads нет вовсе - значит ads=1 не передавали.

Подробнее - в статьях Парсинг рекламной выдачи и Стрелка вверх в выдаче Яндекса.


Параметры поиска по картинкам

Параметры, фильтры и формат ответа - общие для трёх поисковиков: код, который читает results, писать под каждый отдельно не нужно. Методы: /yandex/images, /google/images и /bing/images.

Параметры запроса:

ai=1 в вертикалях возвращает ошибку: блока нейросети на этих страницах не бывает. break_domain и hlword здесь тоже не работают - останавливать перебор на домене и подсвечивать слова запроса в этой выдаче нечем.

Общие фильтры

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

Параметр Значения Яндекс Google Bing
size large, medium, small есть есть1 есть
orientation horizontal, vertical, square есть есть есть
color color, mono, red, orange, yellow, green, teal, blue, purple, white, black, pink, brown кроме pink и brown есть есть
type photo, clipart, lineart, face, animated, transparent, demotivator кроме transparent кроме demotivator кроме demotivator
format jpg, png, gif есть есть только gif
freshness day, week, month, year только week и month2 есть есть
site домен без протокола и пути есть есть нет3

1 У Google меньшая ступень размера одна и означает «значки»: все её картинки ровно 256 px.
2 У Яндекса окна свежести свои - recent=3D, 7D, 14D, 1M; более узкого, чем трое суток, и более широкого, чем месяц, у него нет.
3 Bing отбирает по сайту только в видео.

Фильтры складываются: size=large&orientation=horizontal&format=png. Два фильтра, которые у поисковика попадают в одну ручку (например type=animated и format=png у Яндекса), - ошибка 422.

Родные фильтры поисковика

Всё, чего в общем списке нет, задаётся параметрами самого поисковика и уезжает как есть:

Общий и родной параметр на одну ручку вместе - ошибка 422; у Bing она срабатывает и когда ручку занимает токен внутри qft. Полный разбор - в статье Парсинг картинок из выдачи.

Поля результата:

Первые четыре поля есть всегда и у всех трёх поисковиков. Остальные - необязательные: поля нет, если поисковик значения не дал. Пустой строкой и нулём они не заменяются - ноль читался бы как картинка нулевой ширины.

Поля конверта:


Параметры поиска по видео

Параметры, фильтры и формат ответа - общие для трёх поисковиков, как и у картинок. Методы: /yandex/video, /google/video и /bing/video.

Параметры запроса:

ai=1 в вертикалях возвращает ошибку: блока нейросети на этих страницах не бывает. break_domain и hlword здесь тоже не работают - останавливать перебор на домене и подсвечивать слова запроса в этой выдаче нечем.

Общие фильтры

Параметр Значения Яндекс Google Bing
duration short, medium, long до 10 мин / 10-65 / больше 65 до 4 мин / 4-20 / больше 20 до 5 мин / 5-20 / больше 20
hd 1 есть есть есть (720p и выше)
freshness day, week, month, year нет1 есть есть
site домен без протокола и пути есть нет2 есть

1 У Яндекса окно одно и не настраивается: within=9 - ролики не старше примерно трёх суток.
2 У Google площадка задаётся упакованной строкой tbs=srcf:, собрать её нужно самому.

Ступени duration у всех трёх свои по длине - общий у них смысл ступени, а не её граница. Родные фильтры уезжают как есть: within, lang_filter, host, nohost у Яндекса, tbs=cc:1 (субтитры) и tbs=qdr:h (за час) у Google, resolution=1080p, price=free, short=1 и сырой qft у Bing. Общий и родной параметр на одну ручку вместе - ошибка 422. Подробнее - в статье Парсинг видео из выдачи.

Поля результата:

url, title и domain есть всегда. Остальные поля появляются, только если поисковик их дал.

Отсутствие duration - это «длина неизвестна», а не ноль. Подпись не всегда разбирается в число: у прямых эфиров вместо неё стоит LIVE, встречается и 4:12:30+. Тогда durationText есть, а duration нет. Учтите это в отборе по длине: условие duration < 600 выбросит такие ролики молча, вместе с длинными.

Поля конверта:


Смещение выдачи (page)

По умолчанию выдача собирается с первой страницы, а pages задаёт, сколько страниц собрать подряд. Параметр page сдвигает начало: он говорит, с какой страницы начинать, и работает вместе с pages. page=3&pages=5 - страницы 3–7.

По умолчанию 0. Доступен в /yandex, /google, /bing и в XML-методах.

Нумерация страниц

Нумерация начинается с нуля: page=0 - первая страница. В JSON-методах она всегда такая; параметр page_base там не принимается и возвращает ошибку 422.

В XML-методах нумерацию можно переключить на счёт с единицы - это нужно при переезде с сервисов, где она другая. Описание ниже, в разделах /yandex/xml и /google/xml.

В вертикалях считается иначе

Всё сказанное здесь описывает обычную выдачу, где страница - десять результатов. В поиске по картинкам и видео страница своего размера у каждого поисковика (20, 100, до 35, до 105), поэтому page сдвигает на другое число результатов, start у Google кратен размеру страницы вертикали, а у Bing глубина ограничена не числом страниц, а номером карточки. Точные правила - в общих блоках параметров.

Максимальная глубина

20 страниц, то есть 200 результатов. Предел общий для смещения и ширины окна: сумма page и pages больше 20 - ошибка 422. Одинаково во всех методах, включая XML, где глубина считается как (page + 1) × groupby; там та же ошибка приходит кодом 37 внутри XML с HTTP-статусом 200.

Параметры поисковых систем

То же смещение принимается под теми именами, которыми его называют сами поисковые системы. При одновременной передаче с page используется параметр поисковой системы.

Значение передаётся поисковой системе без изменений. Это единственный способ задать смещение, которое не попадает на границу страницы - например first=19 у Bing.

Особенности Bing

Точное попадание на запрошенное смещение у Bing не гарантируется: границы страниц он двигает сам. page запрашивает круглые границы: page=1 уходит как first=11, page=2 - как first=21. Обычно страницы там и начинаются. При меньшем числе результатов на странице граница смещается, например на 19-й результат - на неё page уже не наведёшь. Ровно на такую границу ставит только first; само значение можно взять из ссылки «Следующая страница» в выдаче Bing.

Ограничения

Когда лучше pages

Несколько страниц подряд следует запрашивать одним запросом через pages, а не несколькими запросами со смещением: выдача динамическая и успевает измениться между обращениями. Разбор - в статье Параметр page: смещение выдачи и почему pages надёжнее. Про расхождение нумерации между сервисами - в статье Нумерация страниц: с нуля или с единицы.

Пример запроса:

curl "https://jsonseo.ru/api/yandex?text=купить+ноутбук&page=2&pages=3&key=ВАШ_КЛЮЧ"
curl "https://jsonseo.ru/api/google?q=купить+ноутбук&start=20&pages=3&key=ВАШ_КЛЮЧ"
curl "https://jsonseo.ru/api/bing?q=купить+ноутбук&first=21&pages=3&key=ВАШ_КЛЮЧ"