Documentation / API reference
API reference
Single capture endpoint, exhaustive option list, webhook contract, and errors. Values mirror captureSchema in the application source.
Overview
ScreenNabster exposes /api/v1/capture for all capture types. The same option object works for GET and POST; only the encoding differs. Successful sync responses are raw bytes. Errors are JSON with error, code, and status.
Base URL for this environment: https://screennabster.vercel.app
Authentication
Header: X-API-Key: pk_…. Required on every call. Keys are created in the dashboard; inactive or unknown keys return 401.
curl -X POST "https://screennabster.vercel.app/api/v1/capture" \
-H "X-API-Key: pk_live_your_key" \
-H "Content-Type: application/json" \
-d "{\"url\":\"https://example.com\"}" \
--output out.pngEndpoint
POST https://screennabster.vercel.app/api/v1/capture
GET https://screennabster.vercel.app/api/v1/capture?…
POST body: JSON object. GET: query parameters with comma-separated arrays and JSON strings where noted in the parameter tables.
Target
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
url | string (URL) | one of url/html | — | Public http(s) page to load. Private IPs, localhost, and metadata hosts are rejected. |
html | string | one of url/html | — | Raw HTML document to render in the browser instead of navigating to url. |
Output
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
output | png | jpg | webp | pdf | html | optional | png | Rendered MIME type / format. |
quality | number 0–100 | optional | 80 | Lossy image quality; ignored for PNG. |
thumb_width | positive int | optional | — | Resize output to this width. |
thumb_height | positive int | optional | — | Resize output to this height. |
Viewport & device
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
screen_width | positive int | optional | 1280 | Viewport width in CSS pixels. |
screen_height | positive int | optional | 800 | Viewport height in CSS pixels. |
screen_landscape | boolean | optional | false | Swap width/height for landscape layout. |
device | string | optional | — | Playwright device preset name (see worker device catalog) or legacy aliases iPad, Galaxy S21. |
device_scale_factor | number 0.5–4 | optional | — | Override device pixel ratio when emulating. |
Page behaviour
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page_full | boolean | optional | false | Capture the full scrollable page. |
wait | int ms 0–10000 | optional | 0 | Extra sleep before screenshot. |
wait_until | load | domcontentloaded | networkidle | commit | optional | load | Playwright navigation wait condition. |
wait_for_selector | string (CSS) | optional | — | Wait until this selector matches before capture. |
scroll_to | number | optional | — | Scroll vertically to this Y offset before capture. |
selector | string (CSS) | optional | — | Clip capture to the first matching element’s bounding box. |
clip_x | number | optional | — | Manual clip rectangle origin X (viewport coords). |
clip_y | number | optional | — | Manual clip rectangle origin Y. |
clip_w | number | optional | — | Manual clip width. |
clip_h | number | optional | — | Manual clip height. |
click_selector | string (CSS) | optional | — | Click element before capture. |
hover_selector | string (CSS) | optional | — | Hover element before capture. |
error_on_click_not_found | boolean | optional | true | Fail if click_selector missing. |
error_on_hover_not_found | boolean | optional | true | Fail if hover_selector missing. |
hide_selectors | string[] | optional | [] | Selectors to hide (display:none) before capture. GET: comma-separated list. |
Appearance & scripting
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
theme_dark | boolean | optional | false | Prefer dark color scheme. |
transparent | boolean | optional | false | Transparent background where supported (e.g. PNG). |
inject_css | string | optional | — | CSS injected before capture. |
inject_js | string | optional | — | JavaScript executed in page before capture. |
PDF options
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pdf_format | A4 | A3 | Letter | Legal | Tabloid | optional | A4 | Printed page size. |
pdf_landscape | boolean | optional | false | Landscape orientation. |
pdf_print_background | boolean | optional | true | Include background graphics in PDF. |
pdf_margin | string | optional | — | Shorthand margin (CSS length). |
pdf_margin_top | string | optional | — | Top margin override. |
pdf_margin_right | string | optional | — | Right margin override. |
pdf_margin_bottom | string | optional | — | Bottom margin override. |
pdf_margin_left | string | optional | — | Left margin override. |
pdf_scale | number 0.1–2 | optional | — | Scale factor for PDF output. |
Blocking & filters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
strip_ads | boolean | optional | false | Block common ad network hosts. |
filters | cookie_banners | ads | popups | chats | trackers | optional | [] | Content filters applied by the worker. GET: comma-separated. |
block_resources | image | stylesheet | font | media | script | xhr | fetch | optional | [] | Playwright resource types to abort. GET: comma-separated. |
Geolocation
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
geo_lat | number −90…90 | optional | — | Emulated latitude. |
geo_lng | number −180…180 | optional | — | Emulated longitude. |
geo_accuracy | positive number | optional | — | Accuracy in meters. |
Browser & HTTP
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
browser_agent | string | optional | — | Custom User-Agent header. |
auth_user | string | optional | — | HTTP Basic username (not stored on async jobs). |
auth_pass | string | optional | — | HTTP Basic password (not stored on async jobs). |
headers | Record<string, string> | optional | — | Extra request headers. Authorization, Cookie, Host, X-Forwarded-For, and worker secrets are rejected. GET: JSON object string. |
Caching & async
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
cached | boolean | optional | false | Use cached render when available. |
background | boolean | optional | false | Queue job; respond with job_id immediately. |
callback_url | string (URL) | optional | — | HTTPS URL for webhook when background job completes or fails. |
Internal
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
storage_bucket | string | optional | — | Reserved for platform use. Do not depend on it in customer integrations. |
Async jobs & webhooks
Set background: true. The API responds immediately with:
{
"job_id": "uuid",
"status": "queued",
"message": "Render queued. Results will be sent to your callback_url."
}Basic auth credentials are stripped before the job is persisted — only the running worker session receives them. When rendering finishes, our backend uploads the binary to private storage, creates a time-limited signed URL, and POSTs to your callback_url if provided.
Webhook headers:
Content-Type: application/jsonX-ScreenNabster-Signature: sha256=<hex>— HMAC-SHA256 of the raw body usingSCREENNABSTER_WEBHOOK_SIGNING_SECRETon our side; verify with the same secret on yours (timing-safe compare).
Success payload shape:
{
"event": "capture.completed",
"job_id": "uuid",
"created_at": "2026-04-11T12:00:00.000Z",
"result_url": "https://…signed…"
}Failure payload shape:
{
"event": "capture.failed",
"job_id": "uuid",
"created_at": "2026-04-11T12:00:00.000Z",
"error": "Worker error message"
}Error codes
JSON body: { "error": string, "code": string, "status": number }. The HTTP status code matches status.
| HTTP | Code | Meaning |
|---|---|---|
401 | MISSING_API_KEY | No X-API-Key header was sent. |
401 | INVALID_API_KEY_FORMAT | Key must start with pk_. |
401 | INVALID_API_KEY | Key not found, revoked, or inactive. |
400 | INVALID_BODY | POST body is not valid JSON. |
400 | VALIDATION_ERROR | Options failed validation (see error text for Zod paths). |
429 | RATE_LIMIT_EXCEEDED | Monthly request quota for this key/user is exhausted. |
500 | QUEUE_ERROR | Background job could not be written to the queue. |
500 | RENDER_ERROR | The render worker failed or timed out for this capture. |