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

Скриншоты веб-страниц: Screenshot API

Снимок веб-страницы через headless Chromium с российских серверов. Ответ — само изображение, а не JSON со ссылкой. Две формы вызова:

Операция Когда использовать
POST /v1/browser/screenshot основной вариант, формат Browserless: все параметры страницы, ожидания, внедрение скриптов, прозрачный фон
GET /v1/browser/screenshot простой снимок по URL одной строкой, например для <img src> на своём бэкенде
Окно терминала
curl -X POST "https://proxy.seyka.ru/v1/browser/screenshot" \
-H "Authorization: Bearer $SEYKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": {"width": 1920, "height": 1080},
"options": {"type": "png", "fullPage": true}
}' \
--output screenshot.png

Тело — общие параметры страницы (url или html, viewport, gotoOptions, waitForSelector и другие) плюс объект options:

Параметр Тип По умолчанию Описание
options.type string jpeg jpeg, png или webp
options.quality integer 80 качество 0–100; применяется к JPEG и WebP
options.fullPage boolean false снять страницу целиком, а не только видимую область
options.omitBackground boolean false прозрачный фон вместо белого (для PNG и WebP)
viewport.width, viewport.height integer 1280, 800 размер окна, 1–4096

Вместо url можно передать готовую разметку — удобно для генерации картинок из шаблона:

Окно терминала
curl -X POST "https://proxy.seyka.ru/v1/browser/screenshot" \
-H "Authorization: Bearer $SEYKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<html><body style=\"font: 64px sans-serif\"><h1>Привет</h1></body></html>",
"viewport": {"width": 1200, "height": 630},
"options": {"type": "png"}
}' \
--output og.png

Для страниц, которые дорисовываются JavaScript, дождитесь нужного элемента:

{
"url": "https://example.com",
"waitForSelector": {"selector": ".content-loaded", "timeout": 5000},
"gotoOptions": {"waitUntil": "networkidle"},
"bestAttempt": true
}

С bestAttempt: true снимок будет сделан, даже если селектор так и не появился.

Окно терминала
curl "https://proxy.seyka.ru/v1/browser/screenshot?url=https://example.com&width=1280&height=800&type=png" \
-H "Authorization: Bearer $SEYKA_API_KEY" \
--output screenshot.png
Параметр Тип По умолчанию Описание
url string — обязательный, адрес страницы
width integer 1280 ширина окна, 320–1920
height integer 800 высота окна, 240–1080
type string jpeg jpeg, png или webp
quality integer 80 качество 10–100; применяется к JPEG и WebP
fullPage string 0 1 или true — страница целиком; 0, false или без параметра — только видимая область
reload string 0 1 или true — снять заново, минуя кэш снимков

GET ждёт события load и не принимает остальные параметры страницы — для ожиданий, куки и заголовков используйте POST.

200 с телом-изображением и Content-Type image/jpeg, image/png или image/webp. Заголовки X-Response-Code, X-Response-Status и X-Response-URL сообщают, что ответил сам сайт; GET-снимок из кэша снимков приходит только с X-Cache: HIT, без этих заголовков. При ошибке приходит JSON с полями error, errorKind и code — см. ошибки Browser API.

Снимок WebP страницы целиком обрезается до 16383 px по каждой стороне — это предел формата WebP.

const response = await fetch('https://proxy.seyka.ru/v1/browser/screenshot', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SEYKA_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ url: 'https://example.com', options: { type: 'png' } }),
});
if (!response.ok) throw new Error((await response.json()).error);
await Bun.write('screenshot.png', await response.arrayBuffer());
console.log(response.headers.get('X-Response-Code')); // код ответа сайта

Кэш ответов шлюза у скриншотов выключен: каждый вызов оплачивается полностью, X-Cache: DISABLED.

У GET есть собственный кэш снимков в памяти сервиса: одинаковый запрос (тот же url, размеры, type, quality, fullPage) может вернуться без нового рендера. Тогда в ответе два заголовка X-Cache: первый — DISABLED от шлюза, второй — HIT или MISS от кэша снимков; клиент, который склеивает повторяющиеся заголовки, увидит DISABLED, HIT. Цена вызова от этого не меняется. Чтобы гарантированно получить свежий снимок, передайте reload=1. У POST собственного кэша нет.

Каждый вызов — по цене скриншота, см. таблицу цен.