API Документация
Базовый адрес: https://glanceshot.com/v1. Все методы используют стандартный HTTP. Параметры можно передавать в строке запроса (GET) или в теле JSON (POST).
Быстрый старт
- Зарегистрируйтесь бесплатно и создайте ключ на странице «API Key» в консоли.
- Передайте ключ в заголовке
X-Access-Keyи вызовите метод создания скриншота:
curl "https://glanceshot.com/v1/screenshot?url=https://example.com&full_page=true" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-o screenshot.pngАутентификация
Каждый запрос требует API Key. Передать его можно любым из способов:
- Заголовок
X-Access-Key: gls_…(рекомендуется для серверных запросов) - Параметр запроса
access_key=gls_…(только для вызовов с сервера, не размещайте его на веб-страницах) - Подписанный URL (если URL нужно разместить на веб-странице — API Key и секрет останутся скрыты)
API Key показывается в открытом виде только один раз — при создании. Сохраните его в надёжном месте. При утечке ключ можно отключить в консоли.
Создание скриншотов
/v1/screenshot/v1/screenshotПараметры только для скриншотов:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| format | enum | png | png, jpeg или webp. |
| device_scale_factor | number | 1 | Коэффициент масштабирования: 1–3. Значение 2 даёт чёткость Retina, размер файла увеличивается примерно в 4 раза. |
| quality | integer | 80 | Качество JPEG / WebP: 1–100. |
| full_page | boolean | false | Скриншот всей страницы. Страница прокручивается экран за экраном для запуска отложенной загрузки. Максимальная высота — 20,000 пикселей. |
| selector | string | — | Скриншот только первого элемента, соответствующего CSS-селектору. Нельзя использовать вместе с full_page. |
Общие параметры для скриншотов и PDF:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| url | string | — | Адрес страницы для скриншота: http или https. Укажите либо этот параметр, либо html. Фрагмент # в URL сохраняется: можно сразу снять нужную страницу одностраничного приложения с hash-маршрутизацией, например https://app.com/#/report/1. |
| html | string | — | HTML-код напрямую (не более 2 MB). Только POST. |
| viewport_width | integer | 1280 | Ширина области просмотра: 320–3840. При значении меньше 768 страница отображается как на мобильном устройстве. |
| viewport_height | integer | 800 | Высота области просмотра: 200–3840. |
| wait_until | enum | networkidle | Стратегия ожидания: domcontentloaded (самая быстрая, для статических страниц), load, networkidle (отслеживает все запросы с момента открытия страницы; после загрузки ждёт 500 мс без активных запросов, но не более 8 секунд дополнительно; подходит для одностраничных приложений). |
| wait_for_selector | string | — | После загрузки страницы ждёт появления и видимости элемента, соответствующего CSS-селектору, и только затем делает скриншот. Ожидание — до 10 секунд; если элемент не появился, возвращается selector_not_found (без списания квоты). Подходит для одностраничных приложений, где контент появляется по таймеру или после анимации, а не по завершении сетевых запросов, например .chart-ready. |
| delay | integer | 0 | Дополнительная задержка после завершения ожидания, в миллисекундах: 0–10000. Позволяет дождаться анимации или отложенной загрузки компонентов. |
| block_ads | boolean | true | Блокирует запросы к рекламным и трекинговым доменам и скрывает рекламные блоки на странице. |
| block_cookie_banners | boolean | true | Скрывает баннеры согласия на использование cookie. |
| dark_mode | boolean | false | Эмулирует prefers-color-scheme: dark. |
| hide_selectors | string | — | Список CSS-селекторов элементов, которые нужно скрыть, например .ad,#popup. |
| cache | boolean | true | Проверять ли кеш. При false страница рендерится заново, но результат всё равно сохраняется в кеше. |
| cache_ttl | integer | 86400 | Срок хранения в кеше, в секундах: 60–2592000. |
| response_type | enum | binary | binary — вернуть файл напрямую; json — вернуть адрес файла и метаданные. |
| proxy | string | — | Необязательный параметр для доступа к целевой странице через ваш прокси (расходы на прокси оплачиваете вы), например из определённой страны или региона. Поддерживаются socks5:// и http://, в том числе с логином и паролем. Формат: socks5://user:pass@203.0.113.10:1080. Передаётся только в теле POST-запроса; недоступен для GET-запросов, подписанных URL и пакетных заданий. Запросы через прокси кешируются отдельно. Если прокси недоступен, аутентификация не пройдена или целевой сайт недоступен через прокси, возвращается proxy_failed. Такие запросы не оплачиваются. |
| cookies | string | object[] | — | Cookie целевого сайта: строка вида sid=abc; theme=dark или массив вида [{"name":"sid","value":"abc"}] (можно указать domain и path). Передаются только целевому сайту, но не сторонним ресурсам на странице. |
| headers | object | — | Дополнительные заголовки запроса, например Authorization: Bearer …. Передаются только целевому сайту. Заголовки, которыми управляет браузер (Host, Cookie, User-Agent и другие), задать нельзя. |
| local_storage | object | — | Данные для записи в localStorage источника (origin) целевого URL. Ключи и значения должны быть строками. |
| session_storage | object | — | Аналогично local_storage, но данные записываются в sessionStorage. |
| login_profile | string | — | Идентификатор профиля входа, сохранённого через расширение браузера (lp_8f2c…). Удобнее, чем передавать cookies напрямую; подходит и для пакетных задач (учётные данные в задачах не сохраняются). |
Скриншоты одностраничных приложений (React, Vue и др.):Перед созданием скриншота страница выполняет JavaScript в настоящем браузере. По умолчанию networkidle ждёт завершения загрузки данных. Если после этого контент появляется по таймеру или после анимации, укажите в wait_for_selector элемент, означающий готовность контента. Если подходящего элемента нет, добавьте время ожидания через delay.
Создание PDF
/v1/pdf/v1/pdfЗа каждый PDF списывается 2 единицы квоты. Перед печатью страница прокручивается, чтобы загрузить отложенный контент. Помимо общих параметров, доступны:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| paper | enum | a4 | Формат бумаги: a4 или letter. Если на странице задано правило @page, настройки страницы имеют приоритет. |
| print_background | boolean | true | Печатать фоновые цвета и изображения. |
| pdf_media | enum | print — стили для печати; screen — экранные стили (как на экране). |
curl -X POST "https://glanceshot.com/v1/pdf" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<h1>Квартальный отчёт</h1><p>Основной текст…</p>", "paper": "a4"}' \
-o report.pdfОтвет API
По умолчанию (response_type=binary) файл возвращается напрямую, а Content-Type соответствует его формату. Заголовки ответа:
X-Request-Id: ID запроса — укажите его при обращении в поддержкуX-Glanceshot-Cache:HITилиMISSX-Glanceshot-Truncated: true: скриншот всей страницы обрезан из-за превышения высоты 20,000 пикселейX-Glanceshot-Format-Changed: webp: PNG размером более 5 MB автоматически преобразован в WebP (при явном указании format=png преобразование не выполняется)
При response_type=json возвращаются адрес файла и метаданные:
curl -X POST "https://glanceshot.com/v1/screenshot" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "response_type": "json"}'
# Возвращает
{
"url": "https://glanceshot.com/i/3f/3f9c….png",
"cache_hit": false,
"duration_ms": 1284,
"format": "png",
"width": 1280,
"height": 800,
"request_id": "req_01j…"
}Подписанные URL
Хотите вставить URL скриншота прямо в <img src>, не раскрывая API Key? Подписанный URL содержит только публичный key_id, без API Key. Подпись вычисляется на вашем сервере с помощью секрета, соответствующего ключу. ID ключа и секрет доступны в консоли на странице API Key:
canonical = Отсортируйте все параметры, кроме signature, в лексикографическом порядке по имени.
Представьте каждый параметр как k=urlencode(v) (RFC 3986, пробел кодируется как %20) и соедините через &
signature = hex(HMAC-SHA256(secret, canonical))Корректная подпись подтверждает авторизацию. Запросы без подписи или с неверной подписью отклоняются. Изменение любого параметра (например, url) делает подпись недействительной. Необязательный параметр expires (в секундах Unix) участвует в подписи; после истечения срока возвращается signature_expired. Чтобы обновить кеш, измените любой незначащий параметр (например, v=2) и заново подпишите URL. Подписанные URL поддерживают только GET-запросы к API скриншотов и PDF; параметры прокси не поддерживаются.
key_id — публичный идентификатор, одного его недостаточно для вызова API. Не добавляйте API Key (access_key) в подписанный URL: такой запрос сразу вернёт invalid_params. Если вы уже размещали API Key на веб-странице, отключите этот ключ в консоли и создайте новый.
import crypto from "node:crypto";
// Кодирование по RFC 3986 (пробел — %20) должно соответствовать правилам сервера
const enc = (v) =>
encodeURIComponent(v).replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase());
function signedUrl(params, keyId, secret) {
const all = { ...params, key_id: keyId };
const canonical = Object.keys(all).sort().map((k) => `${k}=${enc(String(all[k]))}`).join("&");
const signature = crypto.createHmac("sha256", secret).update(canonical).digest("hex");
return `https://glanceshot.com/v1/screenshot?${canonical}&signature=${signature}`;
}
const src = signedUrl({ url: "https://example.com", viewport_width: 1200 }, KEY_ID, SECRET);
// <img src={src} alt="Предпросмотр веб-страницы" />Использование прокси
Если нужно открыть страницу из определённой страны или региона (например, чтобы проверить местный язык, контент или цены), укажите в запросе собственный платный прокси. Расходы на прокси вы оплачиваете самостоятельно. Страница, её изображения, скрипты и запросы к API будут загружаться через этот прокси. Поддерживаются прокси socks5:// и http://, в том числе с именем пользователя и паролем.
curl -X POST "https://glanceshot.com/v1/screenshot" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "proxy": "socks5://user:pass@203.0.113.10:1080"}' \
-o screenshot.pngproxyможно передавать только в теле POST-запроса. Он недоступен для GET-запросов, подписанных URL и пакетных задач, чтобы учётные данные прокси не попадали в URL, историю браузера или на веб-страницы.- Если имя пользователя или пароль содержат специальные символы, такие как
@или:, их нужно предварительно закодировать для URL (например, заменить@на%40). - Запросы с прокси кешируются отдельно: их результаты не используются для запросов без прокси или с другим прокси.
- Если не удалось подключиться к прокси, пройти аутентификацию или открыть целевой сайт, возвращается
proxy_failed. Такие запросы не оплачиваются. Конкретная причина указана вmessage. - У прокси должен быть публичный адрес. Для целевого URL действуют те же ограничения, что и без прокси: доступ к адресам внутренней сети запрещён.
- При доступе к сайтам через прокси соблюдайте условия использования целевого сайта и местное законодательство.
Скриншоты после входа
Чтобы сделать скриншот страницы, доступной только после входа, передайте данные сеанса своей учётной записи. Есть два способа: передать cookies, headers, local_storage, session_storage прямо в запросе или сохранить сеанс как «профиль входа» через расширение Glanceshot для браузера и указать в запросе только login_profile.
curl -X POST "https://glanceshot.com/v1/screenshot" -H "X-Access-Key: $GLANCESHOT_KEY" -H "Content-Type: application/json" -d '{
"url": "https://app.example.com/dashboard",
"cookies": "sid=YOUR_SESSION; theme=dark",
"local_storage": {"token": "YOUR_TOKEN"}
}' -o screenshot.png- Расширение может считывать данные авторизации, недоступные скриптам страницы (включая HttpOnly Cookie), а также localStorage и IndexedDB. Подходит для большинства сайтов. Установите и подключите расширение на странице «Профили входа» в консоли.
- Данные сеанса можно передавать только в теле POST-запроса (
GETи подписанные URL отклоняются). Они не попадают в логи и историю запросов. Запросы с данными сеанса кэшируются отдельно с учётом этих данных; кэш не используется совместно с другими пользователями. - Если данные сеанса переданы, но сайт перенаправляет на страницу входа, возвращается
login_expired. Такой запрос не оплачивается: сеанс больше не действителен, и его нужно повторно синхронизировать через расширение. - Если сеанс сайта привязан к устройству или IP и вход нельзя воспроизвести в облаке (например, в интернет-банке), используйте функцию расширения «Снимок текущей страницы», чтобы сделать скриншот в своём браузере и загрузить его.
Кеширование
Запросы с одинаковыми параметрами используют кеш (пропущенный параметр и явно заданное значение по умолчанию считаются одинаковыми; параметры аутентификации и кеширования не сравниваются). При попадании в кеш в бинарном режиме возвращается перенаправление 302 на адрес файла с заголовком Cache-Control; браузер автоматически переходит по адресу и кеширует файл. В режиме JSON возвращается cache_hit: true.
Запросы из кеша не оплачиваются.Одновременные запросы с одинаковыми параметрами запускают рендеринг только один раз.
Лимиты и оплата
- Оплачиваются только успешные запросы (2xx), не попавшие в кеш: скриншот — 1 единица квоты, PDF — 2.
- При тайм-ауте, сбое рендеринга, ошибке или блокировке доступа на целевом сайте, неверных параметрах или ошибке авторизации квота не расходуется.
- Квота обновляется каждый календарный месяц (UTC). В бесплатном тарифе доступно 100 запросов в месяц; после исчерпания квоты возвращается quota_exceeded.
- При превышении лимита запросов в секунду или одновременных запросов возвращается 429. Заголовок Retry-After содержит рекомендуемое время ожидания в секундах.
- Рендеринг — не более 30 секунд; загрузка данных одной страницы — не более 50 MB; размер итогового файла — не более 50 MB.
Подробные лимиты тарифов: Тарифы.
Коды ошибок
Все ошибки возвращаются в формате JSON:
{
"error": {
"code": "render_failed",
"message": "target responded with an error status",
"upstream_status": 404,
"request_id": "req_01j…"
}
}| HTTP | code | Значение | Оплачивается |
|---|---|---|---|
| 400 | invalid_params | Параметр отсутствует или выходит за допустимый диапазон; message указывает, какой именно | Нет |
| 400 | html_too_large | html превышает 2 MB | Нет |
| 401 | unauthorized | API Key отсутствует, недействителен или отключён | Нет |
| 401 | signature_invalid | Подпись не совпадает (параметры изменены или секрет неверен) | Нет |
| 401 | signature_expired | Срок действия подписанного URL, заданный в expires, истёк | Нет |
| 403 | url_blocked | Доступ к целевому адресу запрещён (например, адрес внутренней сети или localhost) | Нет |
| 408 | render_timeout | Рендеринг превысил 30 секунд | Нет |
| 422 | render_failed | Целевой сайт вернул 4xx/5xx, произошёл сбой DNS или ошибка сертификата; ответ содержит upstream_status | Нет |
| 422 | selector_not_found | По selector не найден элемент или истекло время ожидания wait_for_selector | Нет |
| 422 | too_many_redirects | Более 5 перенаправлений | Нет |
| 422 | site_blocked | Вместо обычного содержимого целевой сайт показал проверку на бота, капчу, страницу входа или отказа в доступе; запрос не тарифицируется | Нет |
| 422 | login_expired | Данные сеанса переданы, но целевой сайт по-прежнему показывает страницу входа. Это означает, что сеанс больше не действителен. | Нет |
| 422 | proxy_failed | Указанный прокси недоступен, аутентификация не пройдена или целевой сайт недоступен через прокси. Конкретная причина указана в message. Запрос не оплачивается. | Нет |
| 429 | rate_limited | Превышен лимит запросов в секунду; повторите запрос согласно Retry-After | Нет |
| 429 | concurrency_exceeded | Превышен лимит одновременных запросов | Нет |
| 429 | quota_exceeded | Месячная квота исчерпана (бесплатный тариф) | Нет |
| 429 | too_many_batches | Более 5 незавершённых пакетных заданий одновременно | Нет |
| 500 | internal | Ошибка сервера. Свяжитесь с нами и укажите request_id | Нет |
Асинхронная обработка
/v1/batch/v1/batch/{id}Отправьте 1–100 адресов одним запросом. Метод сразу вернёт ID задания (HTTP 202), а скриншоты будут создаваться по очереди в фоне. Подходит для пакетной обработки без долгого ожидания ответа. Можно периодически запрашивать статус или указать webhook_url, чтобы получить уведомление по завершении. Аутентификация такая же, как у синхронных методов (только через заголовок или параметр access_key; подписанные URL не поддерживаются).
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| type | enum | screenshot | screenshot (скриншот) или pdf. |
| urls | string[] | — | Адреса для обработки: 1–100. Если хотя бы один некорректен, весь запрос возвращает 400; message указывает его порядковый номер. |
| options | object | {} | Общие параметры для всех URL, совпадающие с параметрами синхронного API (например, full_page, format, viewport_width, cache_ttl). Не могут содержать url, html, response_type, proxy. |
| webhook_url | string | — | Необязательный параметр. Адрес для уведомления после завершения всей обработки. См. раздел «Уведомления о завершении». |
curl -X POST "https://glanceshot.com/v1/batch" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "screenshot",
"urls": ["https://example.com", "https://example.org"],
"options": { "full_page": true, "format": "webp" },
"webhook_url": "https://your-app.com/hooks/glanceshot"
}'
# Возвращает 202
{
"id": "bat_01j…",
"type": "screenshot",
"status": "queued",
"total": 2, "succeeded": 0, "failed": 0,
"created_at": "2026-10-18T09:30:00Z", "completed_at": null,
"webhook": { "url": "https://your-app.com/hooks/glanceshot", "status": "none", "attempts": 0 },
"items": [
{ "index": 0, "url": "https://example.com", "status": "pending", "result": null, "error": null },
{ "index": 1, "url": "https://example.org", "status": "pending", "result": null, "error": null }
]
}Проверка прогресса: статус задания status последовательно принимает значения queued (в очереди), running (обрабатывается), completed (обработка завершена, независимо от результата). Статус каждого адреса — pending, running, succeeded или failed. При успехе result содержит адрес файла, при ошибке error содержит код ошибки (такой же, как у синхронных методов).
curl "https://glanceshot.com/v1/batch/bat_01j…" -H "X-Access-Key: $GLANCESHOT_KEY"
{
"id": "bat_01j…",
"status": "completed",
"total": 2, "succeeded": 1, "failed": 1,
"completed_at": "2026-10-18T09:30:12Z",
"items": [
{
"index": 0, "url": "https://example.com", "status": "succeeded", "duration_ms": 1830,
"result": { "url": "https://glanceshot.com/i/3f/3f9c….webp", "mime": "image/webp", "width": 1280, "height": 2410, "cache_hit": false },
"error": null
},
{
"index": 1, "url": "https://example.org", "status": "failed", "duration_ms": 640,
"result": null,
"error": { "code": "render_failed", "message": "target responded with an error status" }
}
]
}- Оплата как у синхронных методов: за каждый успешно обработанный адрес списывается 1 единица квоты для скриншота или 2 для PDF. Результаты из кеша и ошибки квоту не расходуют.
- Если квота исчерпана при отправке задания, сразу возвращается
quota_exceeded. Если она закончится во время обработки, оставшиеся адреса завершатся с ошибкойquota_exceeded. - На аккаунт допускается не более 5 незавершённых пакетных заданий одновременно. При превышении возвращается
too_many_batches. - Срок хранения файлов результата определяется параметром
options.cache_ttl(по умолчанию 1 день). Скачайте и сохраните их вовремя. - В результатах запроса и уведомлениях
webhook.urlотображается только до пути, без строки запроса.
Уведомления о завершении
Если указан webhook_url, после завершения всего задания мы отправим на него запрос POST с телом JSON: { "event": "batch.completed", "batch": { … } }. Поле batch полностью совпадает с ответом метода проверки статуса. Заголовки:
X-Glanceshot-Signature: t=1760779812,v1=5d3f…:t— время отправки (в секундах Unix),v1— подписьX-Glanceshot-Event: batch.completed,X-Glanceshot-Delivery-Attempt: 1(номер попытки доставки)
v1 = hex(HMAC-SHA256(secret, t + "." + Исходное тело запроса))
secret — секрет для подписи, связанный с API Key, использованным при создании задачи (доступен на странице API Key в консоли).- Верните ответ 2xx в течение 10 секунд, иначе доставка считается неудачной. При сбое выполняется по одной повторной попытке через 10 секунд, 1 минуту и 5 минут (не более 4 попыток всего).
- В редких случаях уведомление об одной задаче может прийти повторно. Удаляйте дубликаты по
batch.id. - Для проверки подписи используйте полученные исходные байты. Убедитесь, что
tотличается от текущего времени не более чем на несколько минут, чтобы предотвратить атаки повторного воспроизведения. - Адрес обратного вызова должен быть общедоступным адресом http(s) и не может указывать на внутреннюю сеть.
import crypto from "node:crypto";
// rawBody должен содержать исходные полученные байты. Нельзя сначала выполнять JSON.parse, а затем повторную сериализацию
function verifyGlanceshotWebhook(rawBody, header, secret, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false; // Защита от повторного воспроизведения
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const got = Buffer.from(parts.v1 ?? "");
return got.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), got);
}
// verifyGlanceshotWebhook(req.rawBody, req.headers["x-glanceshot-signature"], GLANCESHOT_SECRET)Статистика использования
/v1/usagecurl "https://glanceshot.com/v1/usage" -H "X-Access-Key: $GLANCESHOT_KEY"
{ "month": "202610", "used": 37, "limit": 100, "remaining": 63, "overage": 0, "resets_at": "2026-11-01T00:00:00Z", ... }Проверка доступности
/v1/healthНе требует авторизации. Возвращает состояние узла и пула браузеров: общее число, занятые и свободные.