API Reference
Screenshot API converts any URL or HTML snippet into a screenshot or PDF with a single HTTP request. Authenticate with an API key, POST your payload, receive binary image or PDF bytes.
Quickstart
Step 1 — Create a free account at https://screenshotapis.org/signup. Your first API key is created automatically.
Step 2 — Copy your API key from the
dashboard. It looks like
sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Step 3 — Make your first call:
curl -X POST https://screenshotapis.org/v1/screenshot \
-H "X-Api-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "format": "png"}' \
--output screenshot.png
Authentication
Pass your API key in the X-Api-Key request header on every call.
You can also pass it as a Bearer token: Authorization: Bearer sk_live_….
X-Api-Key: sk_live_your_key_here
API keys are shown once on creation. If you lose a key, revoke it in the dashboard and create a new one. Keys are stored as one-way hashes — we can never recover the original value.
POST /v1/screenshot
Returns raw image bytes (image/png, image/jpeg,
or image/webp) on success.
Request body (JSON)
| Field | Type | Default | Description |
|---|---|---|---|
| url | string | — | required* URL to render. Must be http or https. |
| html | string | — | required* Raw HTML to render. Max 5 MB. |
| format | string | png | Output format: png · jpeg · webp |
| viewport_width | int | 1280 | Browser width in px (100–3840) |
| viewport_height | int | 800 | Browser height in px (100–2160) |
| full_page | bool | false | Capture the full scrollable page height |
| quality | int | null | Compression quality 1–100 (jpeg / webp only) |
| delay_ms | int | 0 | Wait N ms after page load (0–10 000). Useful for animations. |
| selector | string | null | CSS selector — capture only that element |
| dark_mode | bool | false | Enable prefers-color-scheme: dark |
| device_scale_factor | float | 1.0 | Pixel ratio (0.5–3.0). Use 2.0 for retina. |
| block_ads | bool | false | Block ads and tracking scripts |
| hide_cookie_banners | bool | false | Hide common cookie consent banners |
| inject_css | string | null | Custom CSS to inject into the page |
| inject_js | string | null | Custom JavaScript to inject into the page |
| wait_until | string | networkidle | Wait strategy: load · domcontentloaded · networkidle |
| user_agent | string | null | Custom User-Agent string |
| webhook_url | string | null | URL to POST results to. Returns 202 immediately, delivers async. |
* Exactly one of url or html must be provided.
Example — OG image from HTML
curl -X POST https://screenshotapis.org/v1/screenshot \
-H "X-Api-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"html": "<div style=\"width:1200px;height:630px;background:#0d6efd;color:#fff;display:flex;align-items:center;justify-content:center;font-size:3rem\">My Article Title</div>",
"viewport_width": 1200,
"viewport_height": 630,
"device_scale_factor": 2
}' \
--output og-image.png
Example — retina full-page screenshot
curl -X POST https://screenshotapis.org/v1/screenshot \
-H "X-Api-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","full_page":true,"device_scale_factor":2}' \
--output fullpage.png
POST /v1/pdf
Returns raw PDF bytes (application/pdf) on success with a
Content-Disposition: attachment; filename=render.pdf header.
Request body (JSON)
| Field | Type | Default | Description |
|---|---|---|---|
| url | string | — | required* URL to render |
| html | string | — | required* Raw HTML to render. Max 5 MB. |
| format | string | A4 | Paper size: A4 · Letter · Legal · A3 · Tabloid |
| landscape | bool | false | Landscape orientation |
| margin_top | string | 1cm | Top margin (CSS units: 1cm, 20px, etc.) |
| margin_right | string | 1cm | Right margin |
| margin_bottom | string | 1cm | Bottom margin |
| margin_left | string | 1cm | Left margin |
| print_background | bool | true | Include background colors and images |
| display_header_footer | bool | false | Show header and footer |
| header_template | string | "" | HTML for the page header (Chromium template) |
| footer_template | string | "" | HTML for the page footer |
| block_ads | bool | false | Block ads and tracking scripts |
| hide_cookie_banners | bool | false | Hide common cookie consent banners |
| inject_css | string | null | Custom CSS to inject into the page |
| inject_js | string | null | Custom JavaScript to inject into the page |
| wait_until | string | networkidle | Wait strategy: load · domcontentloaded · networkidle |
| user_agent | string | null | Custom User-Agent string |
| webhook_url | string | null | URL to POST results to. Returns 202 immediately, delivers async. |
Example — HTML to PDF invoice
curl -X POST https://screenshotapis.org/v1/pdf \
-H "X-Api-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"html": "<html><body><h1>Invoice #42</h1><p>Amount due: $100</p></body></html>",
"format": "A4",
"margin_top": "2cm",
"margin_bottom": "2cm"
}' \
--output invoice.pdf
GET /v1/usage
Returns current usage statistics for the authenticated user.
Response (JSON)
{
"plan": "growth",
"credits_remaining": 5843,
"renders_today": 12,
"renders_this_month": 157,
"renders_total": 2841
}
Error codes
| Status | When it happens |
|---|---|
| 400 | Invalid URL, blocked scheme (not http/https), or private IP (SSRF guard) |
| 401 | Missing or invalid X-Api-Key |
| 402 | Insufficient credits — upgrade or buy a credit pack |
| 422 | Render failed: page error, JS crash, selector not found, or timeout |
| 429 | Rate limit exceeded — see rate limits |
Error bodies follow the format: {"detail": "Human-readable message."}
On a 422, the credit is refunded — you are never charged for a failed render.
Rate limits
Rate limits apply per API key. The window is a 60-second sliding window.
| Plan | Requests / minute | Monthly credits |
|---|---|---|
| free | 10 | 100 |
| starter | 30 | 2,000 |
| growth | 60 | 6,000 |
| business | 120 | 25,000 |
| scale | 300 | 75,000 |
When a rate limit is hit the API returns HTTP 429 with header
Retry-After: 60.
Response headers
| Header | Description |
|---|---|
| X-Render-Time-Ms | How long the render took in milliseconds |
| X-Credits-Remaining | Credits left on your account after this render |
| X-Request-Id | Unique request ID — include in support requests |
Webhook callbacks
Add webhook_url to any screenshot or PDF request to receive results asynchronously.
The API returns 202 Accepted immediately with a render_id, then POSTs the result to your URL when done.
Request
curl -X POST https://screenshotapis.org/v1/screenshot \
-H "X-Api-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","webhook_url":"https://your-server.com/hook"}'
Immediate response (202)
{
"render_id": "render_a1b2c3d4e5f6g7h8",
"status": "processing",
"webhook_url": "https://your-server.com/hook"
}
Webhook POST payload
{
"render_id": "render_a1b2c3d4e5f6g7h8",
"success": true,
"url": "https://cdn.screenshotapis.org/renders/42/2026-04-11/abc123.png",
"content_type": "image/png",
"render_time_ms": 1230,
"output_size_bytes": 184320,
"error": null,
"timestamp": 1744300000
}
Verifying webhook signatures
Every webhook POST includes an X-Webhook-Signature header — an HMAC-SHA256 hex digest
of the JSON body, signed with your API key. Verify it to confirm the payload came from us:
import hmac, hashlib
def verify(body: bytes, signature: str, api_key: str) -> bool:
expected = hmac.new(api_key.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)