SerpAPI
Живая выдача Google в структурированном JSON: web, Maps, Shopping, News, Images,
YouTube, Scholar, Jobs, Trends. Один эндпоинт, движок выбирается параметром
engine. Капчи и прокси на стороне сервиса — браузер не нужен.
Ключ
SERPAPI_API_KEY из ~/.claude/.credentials.master.env, читать через
os.getenv. Каждый вызов списывает единицу квоты плана — при отладке не гоняй
цикл по страницам вслепую. Тарифы и лимиты → references/pricing-and-limits.md.
Ключа нет — что тогда
Без SERPAPI_API_KEY любой вызов вернёт 401 Invalid API key, а не «ключ не задан».
Бесплатного тарифа, которого хватает на работу, у SerpAPI нет.
Два пути, оба ниже в этом файле:
openserp в Docker — раздел «Локальная бесплатная альтернатива»: живая выдача
Google/Yandex/Bing/DuckDuckGo, 0 кредитов. Structured-блоков (carousels, Maps,
Shopping, Trends) не отдаёт.
- Встроенный веб-поиск Claude Code — когда нужен ответ, а не разбор выдачи по
позициям.
Вызов
import os, requests
def serp(engine: str, **params) -> dict:
r = requests.get("https://serpapi.com/search", params={
"api_key": os.getenv("SERPAPI_API_KEY"),
"engine": engine, "output": "json",
"hl": "en", "gl": "us", **params,
})
r.raise_for_status()
return r.json()
Есть официальная обёртка, но ставится она под неочевидным именем:
pip install google-search-results, а импорт при этом from serpapi import GoogleSearch. Возможностей она не добавляет — тот же GET с теми же параметрами.
Локальная бесплатная альтернатива
Для простого парсинга живой выдачи (без carousels/Maps/Shopping/Trends — за
структурой оставайся на SerpAPI) — self-hosted karust/openserp в Docker,
127.0.0.1:7000, 0 кредитов. Поддерживает Google/Yandex/Bing/DuckDuckGo.
DuckDuckGo/Bing работают из коробки; Google и особенно Yandex (которого
SerpAPI не отдаёт вообще) из коробки капчатся/ратлимитятся без прокси — нужен
--proxy/--2captcha_key на старте контейнера. Полные детали, эндпоинты, гочи
→ ~/.claude/skills/seo-machine-ru/SKILL.md, секция «Яндекс/Google SERP локально
(openserp)».
Движки: параметр запроса и ключ результатов
Ключ, под которым лежат результаты, из имени движка не выводится — угадаешь
неверно, получишь пустой список и решишь, что выдача пустая.
| engine |
запрос кладётся в |
результаты в |
google |
q |
organic_results + knowledge_graph, answer_box, related_questions, related_searches |
google_maps |
q |
local_results |
google_shopping |
q |
shopping_results |
google_news |
q |
news_results |
google_images |
q |
images_results (не image_) |
youtube |
search_query (не q) |
video_results |
google_scholar |
q |
organic_results |
google_jobs |
q |
jobs_results |
google_trends |
q |
interest_over_time, related_queries, related_topics |
google_videos, google_local, google_patents |
q |
распечатай results.keys() — здесь не зафиксировано |
Параметры, которые не угадываются
| Задача |
Параметр |
| Язык / страна выдачи |
hl=en, gl=us |
| Вторая страница |
start=10 (третья — 20) |
| Свежесть: день/неделя/месяц/год |
tbs=qdr:d / qdr:w / qdr:m / qdr:y |
| Вилка цен в Shopping |
tbs=mr:1,price:1,ppr_min:50 (и/или ppr_max:200) |
| Размер картинки |
tbs=isz:l (m средние, i иконки) |
| Тип картинки |
tbs=itp:photo (clipart, lineart) |
| Публикации от года (Scholar) |
as_ylo=2023 |
| Точка на карте |
ll=@55.75,37.61,15z — с @ и z-зумом; либо location=Moscow |
| Окно Trends |
date="today 12-m" (now 1-H, now 7-d, today 1-m) + data_type=TIMESERIES |
tbs — одна строка: несколько фильтров склеиваются через запятую, второе
присваивание затирает первое.
Вложенные поля ответа
Часть значений лежит глубже, чем кажется по названию:
- News:
source.name (не source)
- YouTube:
channel.name, thumbnail.static
- Scholar:
publication_info.summary, inline_links.cited_by.total,
PDF — resources[0].link (списка resources может не быть вовсе)
- Jobs:
detected_extensions.posted_at, detected_extensions.salary
- Shopping:
price — строка с валютой, число для сравнения — extracted_price
- Maps:
gps_coordinates, hours
Гочи
- Результаты кэшируются ~30 секунд: повтор идентичного запроса вернёт тот же
снимок. Если нужна свежесть после правки — меняй параметры, а не жми повтор.
- Локаль решает состав выдачи:
gl/hl меняют не только язык подписей, но и
набор блоков (answer_box, «People also ask» появляются не везде).
1---2name: serpapi3description: Google Search API через SerpAPI (SERPAPI_API_KEY): выдача, Maps, Shopping, News, YouTube. Триггеры: «спарси выдачу гугла», «цены google shopping».4---56# SerpAPI78Живая выдача Google в структурированном JSON: web, Maps, Shopping, News, Images,9YouTube, Scholar, Jobs, Trends. Один эндпоинт, движок выбирается параметром10`engine`. Капчи и прокси на стороне сервиса — браузер не нужен.1112## Ключ1314`SERPAPI_API_KEY` из `~/.claude/.credentials.master.env`, читать через15`os.getenv`. Каждый вызов списывает единицу квоты плана — при отладке не гоняй16цикл по страницам вслепую. Тарифы и лимиты → `references/pricing-and-limits.md`.1718<!-- no-key-block -->19### Ключа нет — что тогда2021Без `SERPAPI_API_KEY` любой вызов вернёт `401 Invalid API key`, а не «ключ не задан».22Бесплатного тарифа, которого хватает на работу, у SerpAPI нет.2324Два пути, оба ниже в этом файле:25261. **`openserp` в Docker** — раздел «Локальная бесплатная альтернатива»: живая выдача27 Google/Yandex/Bing/DuckDuckGo, 0 кредитов. Structured-блоков (carousels, Maps,28 Shopping, Trends) не отдаёт.292. **Встроенный веб-поиск Claude Code** — когда нужен ответ, а не разбор выдачи по30 позициям.3132## Вызов3334```python35import os, requests3637def serp(engine: str, **params) -> dict:38 r = requests.get("https://serpapi.com/search", params={39 "api_key": os.getenv("SERPAPI_API_KEY"),40 "engine": engine, "output": "json",41 "hl": "en", "gl": "us", **params,42 })43 r.raise_for_status()44 return r.json()45```4647Есть официальная обёртка, но ставится она под неочевидным именем:48`pip install google-search-results`, а импорт при этом `from serpapi import49GoogleSearch`. Возможностей она не добавляет — тот же GET с теми же параметрами.5051## Локальная бесплатная альтернатива5253Для простого парсинга живой выдачи (без carousels/Maps/Shopping/Trends — за54структурой оставайся на SerpAPI) — self-hosted `karust/openserp` в Docker,55`127.0.0.1:7000`, 0 кредитов. Поддерживает Google/Yandex/Bing/DuckDuckGo.56DuckDuckGo/Bing работают из коробки; Google и особенно **Yandex** (которого57SerpAPI не отдаёт вообще) из коробки капчатся/ратлимитятся без прокси — нужен58`--proxy`/`--2captcha_key` на старте контейнера. Полные детали, эндпоинты, гочи59→ `~/.claude/skills/seo-machine-ru/SKILL.md`, секция «Яндекс/Google SERP локально60(openserp)».6162## Движки: параметр запроса и ключ результатов6364Ключ, под которым лежат результаты, из имени движка не выводится — угадаешь65неверно, получишь пустой список и решишь, что выдача пустая.6667| engine | запрос кладётся в | результаты в |68|---|---|---|69| `google` | `q` | `organic_results` + `knowledge_graph`, `answer_box`, `related_questions`, `related_searches` |70| `google_maps` | `q` | `local_results` |71| `google_shopping` | `q` | `shopping_results` |72| `google_news` | `q` | `news_results` |73| `google_images` | `q` | `images_results` (не `image_`) |74| `youtube` | **`search_query`** (не `q`) | `video_results` |75| `google_scholar` | `q` | `organic_results` |76| `google_jobs` | `q` | `jobs_results` |77| `google_trends` | `q` | `interest_over_time`, `related_queries`, `related_topics` |78| `google_videos`, `google_local`, `google_patents` | `q` | распечатай `results.keys()` — здесь не зафиксировано |7980## Параметры, которые не угадываются8182| Задача | Параметр |83|---|---|84| Язык / страна выдачи | `hl=en`, `gl=us` |85| Вторая страница | `start=10` (третья — 20) |86| Свежесть: день/неделя/месяц/год | `tbs=qdr:d` / `qdr:w` / `qdr:m` / `qdr:y` |87| Вилка цен в Shopping | `tbs=mr:1,price:1,ppr_min:50` (и/или `ppr_max:200`) |88| Размер картинки | `tbs=isz:l` (`m` средние, `i` иконки) |89| Тип картинки | `tbs=itp:photo` (`clipart`, `lineart`) |90| Публикации от года (Scholar) | `as_ylo=2023` |91| Точка на карте | `ll=@55.75,37.61,15z` — с `@` и `z`-зумом; либо `location=Moscow` |92| Окно Trends | `date="today 12-m"` (`now 1-H`, `now 7-d`, `today 1-m`) + `data_type=TIMESERIES` |9394`tbs` — одна строка: несколько фильтров склеиваются через запятую, второе95присваивание затирает первое.9697## Вложенные поля ответа9899Часть значений лежит глубже, чем кажется по названию:100101- News: `source.name` (не `source`)102- YouTube: `channel.name`, `thumbnail.static`103- Scholar: `publication_info.summary`, `inline_links.cited_by.total`,104 PDF — `resources[0].link` (списка `resources` может не быть вовсе)105- Jobs: `detected_extensions.posted_at`, `detected_extensions.salary`106- Shopping: `price` — строка с валютой, число для сравнения — `extracted_price`107- Maps: `gps_coordinates`, `hours`108109## Гочи110111- Результаты кэшируются ~30 секунд: повтор идентичного запроса вернёт тот же112 снимок. Если нужна свежесть после правки — меняй параметры, а не жми повтор.113- Локаль решает состав выдачи: `gl`/`hl` меняют не только язык подписей, но и114 набор блоков (`answer_box`, «People also ask» появляются не везде).