Smart Scrape: документ по URL с автоматическим выбором способа
POST /v1/browser/smart-scrape получает документ по URL самым дешёвым из доступных способов: из кэша, из
сохранённой копии поисковой системы, прямым HTTP-запросом и только при необходимости — в headless Chromium.
Ответ — JSON с содержимым, его видом (contentKind), Markdown, ссылками и SEO-данными. HTML, JSON, XML, текст,
PDF и таблицы Excel читаются одним и тем же запросом.
Пакетный вариант в формате Tavily — POST /v1/tavily/extract, см. ниже.
curl -X POST "https://proxy.seyka.ru/v1/browser/smart-scrape?timeout=30000" \ -H "Authorization: Bearer $SEYKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com", "formats": ["content", "markdown"]}'const res = await fetch('https://proxy.seyka.ru/v1/browser/smart-scrape?timeout=30000', { method: 'POST', headers: { Authorization: `Bearer ${process.env.SEYKA_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ url: 'https://example.com', formats: ['content', 'markdown'] }),});const data = await res.json();if (data.ok) { console.log(data.contentKind); // "html" | "json" | "xml" | "text" | "pdf" | "spreadsheet" console.log(data.markdown);} else { console.error(`${data.message} (strategy: ${data.strategy})`);}import os, httpx
r = httpx.post( "https://proxy.seyka.ru/v1/browser/smart-scrape", params={"timeout": 30000}, json={"url": "https://example.com", "formats": ["content", "markdown"]}, headers={"Authorization": f"Bearer {os.environ['SEYKA_API_KEY']}"}, timeout=80,)data = r.json()if data["ok"]: print(data["contentKind"], data["markdown"][:200])else: print(data["message"], data["strategy"])| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
url |
string |
— | обязательный, HTTP(S)-адрес |
formats |
string[] |
["content"] |
что вернуть: content, markdown, links, seo, screenshot, pdf; html — синоним content |
Query-параметр timeout — в миллисекундах, 1000–60000, по умолчанию 30000. Он действует отдельно на прямой
HTTP-запрос и на попытку в браузере; попытка сохранённой копии ограничена двумя секундами. Шлюз ждёт ответа
не дольше 75 секунд, поэтому медленный запрос с timeout около максимума, дошедший до браузера, может
завершиться ошибкой 502.
Форматы screenshot и pdf сразу запускают браузер; если запрошены оба, они снимаются с одной загрузки
страницы. Неизвестные поля тела (например, proxy из Browserless) игнорируются.
- Кэш документов — общий для Smart Scrape и Cheerio, документ живёт в нём 12 часов.
- Сохранённая копия из кэша поисковой системы — только для HTML и только если URL не оканчивается явным
расширением «сырого» файла (
.json,.xml,.pdfи т. п.). - Прямой HTTP-запрос к источнику.
- Headless Chromium — для страниц, которые строятся JavaScript, и для некачественных HTTP-ответов (пустая или слишком короткая страница, оболочка без содержимого).
В ответе strategy — сработавшая ступень: cache, yandex-cache (сохранённая копия), http-fetch или
browser; attempted — все сделанные попытки по порядку.
В браузер запрос переходит не всегда:
- «сырой» документ — JSON, XML, текст, PDF, таблица — получается только прямым запросом. Ответ 2xx сразу возвращается, а ошибка или не-2xx на «сыром» URL завершают каскад: Chromium не прочитает исходник лучше, а PDF и таблицы вообще скачивает, а не открывает;
- HTML-ответ 2xx идёт обычным путём, даже если URL выглядит как «сырой» файл;
- ответ 2xx с распознанным, но неподдерживаемым типом (
image/png,application/msword) завершается без браузера; исключение —application/octet-stream, потому что источник может отдать браузеру другое; - слишком большой ответ тоже завершается без браузера — рендер не сделает документ меньше.
Вид документа: contentKind
Заголовок раздела «Вид документа: contentKind»contentKind говорит, как читать content. Он описывает сам ресурс и возвращается всегда, когда документ
получен, даже если формат content не запрошен. Ветвитесь по нему, а не по contentType.
contentKind |
MIME-типы | Что лежит в content |
|---|---|---|
html |
text/html, application/xhtml+xml |
очищенный HTML: удалены скрипты, стили, iframe, обработчики событий, ссылки javascript: и data: |
json |
application/json, text/json, application/*+json |
исходный текст как есть, без очистки |
xml |
application/xml, text/xml, image/svg+xml, application/*+xml |
исходный текст как есть, без очистки |
text |
text/plain, text/markdown, text/csv, text/css, text/javascript, application/robots+txt и другие text/* |
исходный текст как есть, без очистки |
pdf |
application/pdf |
извлечённый текстовый слой, не байты файла |
spreadsheet |
Excel (.xls, .xlsx, .xlsm, .xlsb), OpenDocument (.ods) и их шаблоны |
CSV; несколько листов разделяются строками === Sheet: имя === |
Вид определяется по Content-Type ответа — он всегда важнее расширения в URL. Расширение конечного URL
(после редиректов) учитывается, только если заголовка нет или он не говорит о формате
(application/octet-stream); если заголовка нет и расширение ничего не подсказывает, документ считается HTML. text/event-stream и
нераспознанные типы — изображения, .doc, бинарные файлы без подсказки — документом не считаются.
{ "ok": true, "statusCode": 200, "content": "<html><head><title>Example Domain</title></head><body>…</body></html>", "contentKind": "html", "contentType": "text/html; charset=utf-8", "headers": { "content-type": "text/html; charset=utf-8" }, "redirects": [], "strategy": "http-fetch", "attempted": ["cache", "http-fetch"], "message": null, "screenshot": null, "pdf": null, "markdown": "# Example Domain\n\nThis domain is for use in illustrative examples…", "links": null, "seo": null}| Поле | Описание |
|---|---|
ok |
получен ли документ |
statusCode, contentType, headers |
код, тип и безопасные заголовки ответа источника; Set-Cookie, авторизационные и подобные заголовки не передаются |
redirects |
цепочка редиректов: from, to, statusCode |
content, contentKind |
документ и его вид; content — null, если формат content не запрошен |
markdown |
Markdown документа (см. ниже) |
links, seo |
ссылки и SEO-данные — только для HTML, для остальных видов null |
screenshot, pdf |
PNG и PDF страницы в base64, если запрошены |
strategy, attempted |
сработавшая ступень и все попытки |
message |
диагностика, если ok: false |
Конечный адрес документа приходит в заголовке X-Response-URL.
markdown строится по виду: для HTML — из очищенной страницы; для text — сам исходник; для xml —
таблица sitemap или список записей RSS/Atom, иначе блок кода; для json — исходник в блоке кода; для
pdf — извлечённый текст; для spreadsheet — таблица по каждому листу, не больше 100 строк на лист с
пометкой об остальных (content при этом не усекается).
Тело декодируется по объявленной кодировке — BOM, charset заголовка, <meta charset> или объявление XML,
иначе UTF-8, — поэтому сайты в windows-1251 читаются одинаково на всех ступенях.
Неудача — это 200 с ok: false
Заголовок раздела «Неудача — это 200 с ok: false»Если ни одна ступень не дала документ, HTTP-статус всё равно 200: в теле ok: false, message с причиной
и content, contentKind равны null, а statusCode, contentType, заголовки и редиректы описывают
последнюю попытку. Проверяйте ok, а не только код ответа. В смешанном запросе вроде
["content", "screenshot"] скриншот при этом остаётся в ответе.
Ошибки самого запроса — неверный URL, адрес во внутренней сети, неизвестный формат, timeout вне диапазона —
возвращают 400 до начала работы.
| Ситуация | content |
contentKind |
|---|---|---|
документ получен, content запрошен |
строка | вид документа |
документ получен, content не запрошен |
null |
вид документа |
запрошены только screenshot и/или pdf |
null |
null |
| каскад исчерпан, не-2xx, неподдерживаемый тип | null |
null |
Ограничения
Заголовок раздела «Ограничения»- Текстовый документ — до 4 МиБ, PDF и таблица — до 10 МиБ; крупнее —
ok: false. - Текст, извлечённый из PDF или таблицы, — не больше 1,5 МБ.
- Скан PDF без текстового слоя —
ok: falseсmessage: "PDF has no text layer". - PDF и таблицы извлекаются только прямым HTTP-запросом: если он не прошёл, браузер не поможет.
Примеры
Заголовок раздела «Примеры»Свежие данные
Заголовок раздела «Свежие данные»Заголовок Cache-Control: no-cache пропускает кэш ответов шлюза, кэш документов и сохранённую копию и
идёт сразу к источнику; ответ приходит с X-Cache: BYPASS, а свежий результат обновляет кэши. Учтите, что
без дешёвых ступеней запрос чаще доходит до браузера.
curl -s -D - -X POST "https://proxy.seyka.ru/v1/browser/smart-scrape" \ -H "Authorization: Bearer $SEYKA_API_KEY" \ -H "Content-Type: application/json" \ -H "Cache-Control: no-cache" \ -d '{"url": "https://example.com", "formats": ["content"]}'# x-cache: BYPASS; в теле strategy — "http-fetch" или "browser"SEO и ссылки
Заголовок раздела «SEO и ссылки»Форматы seo и links работают для HTML-документов:
curl -s -X POST "https://proxy.seyka.ru/v1/browser/smart-scrape" \ -H "Authorization: Bearer $SEYKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com", "formats": ["seo", "links"]}'{ "links": ["https://www.iana.org/domains/example"], "seo": { "title": "Example Domain", "metadata": { "viewport": "width=device-width, initial-scale=1" }, "canonical": null, "language": null, "headings": [{ "level": 1, "text": "Example Domain" }], "links": [{ "url": "https://www.iana.org/domains/example", "text": "More information..." }], "images": [], "jsonLd": [], "diagnostics": [] }}seo содержит title, мета-теги (metadata), canonical, language, заголовки h1–h6, ссылки
(url, text, rel), изображения (src, alt, title), разобранные блоки JSON-LD и diagnostics —
замечания с полями code и message.
Скриншот
Заголовок раздела «Скриншот»Визуальные форматы идут сразу в браузер. PNG приходит в поле screenshot в base64:
curl -s -X POST "https://proxy.seyka.ru/v1/browser/smart-scrape" \ -H "Authorization: Bearer $SEYKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com", "formats": ["screenshot"]}' \ | jq -r '.screenshot // empty' | base64 -d > page.pngЗдесь contentKind равен null: документ не запрашивался. Запрос ["screenshot", "markdown"] вернёт и
скриншот, и contentKind.
PDF и таблицы
Заголовок раздела «PDF и таблицы»Запрос ничем не отличается от обычного — вид придёт в contentKind:
curl -s -X POST "https://proxy.seyka.ru/v1/browser/smart-scrape" \ -H "Authorization: Bearer $SEYKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com/stats.xlsx", "formats": ["content", "markdown"]}'# contentKind: "spreadsheet"; content — CSV, markdown — таблицы по листамЦена и кэш
Заголовок раздела «Цена и кэш»Smart Scrape оплачивается по ступени, на которой получен документ, и тарифицируется по двум позициям таблицы цен:
- дешёвая ступень — кэш документов, сохранённая копия или прямой HTTP-запрос, без запуска браузера;
- рендер в браузере — любая попытка Chromium, включая неудачную, а также все запросы с
screenshotилиpdf. Если все браузеры были заняты и рендер так и не начался, вызов не оплачивается.
Баланс перед вызовом проверяется по цене рендера в браузере, а списывается фактическая ступень.
Поверх каскада работает кэш ответов шлюза. Повтор запроса с тем же URL и тем же набором форматов в пределах
окна кэша возвращается с X-Cache: HIT, strategy: "cache" и оплачивается по цене повтора из кэша, без
обращения к браузеру. URL сравнивается в канонической форме; порядок и повторы форматов, html вместо
content и timeout на совпадение не влияют. Не кэшируются ответы с ok: false, с screenshot или
pdf (X-Cache: UNCACHEABLE), ответы, которые источник пометил no-store, и слишком большие ответы.
Tavily Extract
Заголовок раздела «Tavily Extract»POST /v1/tavily/extract — пакетное извлечение в формате Tavily Extract: до 20 URL
за запрос через тот же каскад. Существующий клиент Tavily достаточно направить на https://proxy.seyka.ru —
путь POST /extract у базового адреса работает как синоним. Поиск в формате Tavily описан в разделе
Tavily.
curl -X POST "https://proxy.seyka.ru/v1/tavily/extract" \ -H "Authorization: Bearer $SEYKA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"urls": ["https://example.com", "http://10.0.0.1/"], "timeout": 30}'| Поле | Тип | Описание |
|---|---|---|
urls |
string или string[] |
обязательный, один адрес или до 20 |
timeout |
number |
секунды, 1–60, по умолчанию 30 — на весь запрос, включая ожидание свободного браузера |
extract_depth, format |
string |
принимаются для совместимости и ни на что не влияют |
{ "results": [ { "url": "https://example.com", "raw_content": "# Example Domain\n\nThis domain is for use in…" } ], "failed_results": [ { "url": "http://10.0.0.1/", "error": "Access to private IPs not allowed" } ], "response_time": 1.84}raw_content— всегда Markdown документа, независимо отformat; в сумме не больше 16 МиБ на ответ. Документы сверх лимита попадают вfailed_resultsс просьбой запросить меньше URL, но оплачиваются по своей ступени — работа уже сделана.failed_results— адреса, которые не удалось получить, с причиной;response_time— в секундах.- Пустой
urls—400; больше 20 адресов —413. Если сервис перегружен пакетами, ответ503с заголовкомRetry-After. - Ответы не кэшируются шлюзом и не несут
X-Cache, но каскад, включая кэш документов, работает как обычно.
Каждый уникальный URL оплачивается по ступени, на которой он получен: дешёвая ступень или рендер в браузере, включая исчерпанный каскад. Отклонённые адреса, ошибки сервиса и занятый пул браузеров не оплачиваются. Итог приходит в заголовках:
X-Cost-Cents— списанная сумма в копейках;X-Extract-Tiers— сколько URL прошло по каждой ступени, напримерcheap=3,browser=2.
Перед вызовом баланс проверяется по цене рендера в браузере за каждый уникальный URL.
Миграция с Browserless
Заголовок раздела «Миграция с Browserless»https://production-sfo.browserless.io/smart-scrapehttps://proxy.seyka.ru/v1/browser/smart-scrapeЗапросы Browserless Smart Scrape работают без изменений: formats: ["html"] принимается как content,
поле proxy игнорируется. Отличия ответа:
- обязательное поле
contentKind— ветвитесь по нему;contentдля HTML приходит очищенным, а не сырым; - неудача —
200сok: falseи данными последней попытки, а не код ошибки; - добавлены формат
seo, каскад с общим кэшем документов и сохранённой копией и двухступенчатая тарификация.
Остальные эндпоинты Browserless — см. обзор Browser API.