Screenshots
Capture pixel-perfect screenshots of HTML content or live URLs as PNG, JPEG, or WebP images.
The default render timeout is 30 seconds. For complex pages with many external resources, you can increase this up to 60 seconds using the timeout option. See the options table below.
Endpoint
POST https://pixdoc.dev/api/v1/screenshot
Request Body
Provide exactly one content source (html or url) along with an optional options object.
| Field | Type | Description |
|---|---|---|
html | string | Raw HTML to render and capture |
url | string | URL of a page to capture |
options | object | Rendering options (see below) |
metadata | object | Arbitrary JSON metadata (max 1KB) attached to the render. Returned in the polling endpoint and webhook payloads. Useful for reconciling renders with your own system (e.g., order IDs, customer references). |
You must provide exactly one of html or url. Sending both or neither returns a 400 error.
Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
width | integer | 1280 | Viewport width in pixels (minimum: 1) |
height | integer | 800 | Viewport height in pixels (minimum: 1) |
format | "png" | "jpeg" | "webp" | "png" | Output image format |
quality | integer | 80 | Image quality for JPEG and WebP (1–100). Ignored for PNG |
fullPage | boolean | false | Capture the entire scrollable page, not just the viewport |
selector | string | null | null | CSS selector of a specific element to capture |
deviceScaleFactor | 1 | 2 | 3 | 1 | Pixel density. Use 2 for retina-quality screenshots |
darkMode | boolean | false | Emulate prefers-color-scheme: dark |
blockAds | boolean | false | Block common ad networks and trackers |
injectCSS | string | null | null | Custom CSS to inject before capturing |
waitForSelector | string | null | null | CSS selector to wait for before capturing |
waitForTimeout | number | null | null | Milliseconds to wait before capturing |
timeout | number | 30000 | Maximum render time in milliseconds (1000–60000) |
cookies | array | [] | Cookies to set before loading. Each: {name, value, domain} |
extraHeaders | object | {} | Additional HTTP headers to send with the request |
Code Examples
Basic Screenshot
curl -X POST https://pixdoc.dev/api/v1/screenshot \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"metadata": {"project": "website-audit", "page": "homepage"}
}' \
-o screenshot.pngFull-Page Retina Screenshot
curl -X POST https://pixdoc.dev/api/v1/screenshot \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"options": {
"fullPage": true,
"deviceScaleFactor": 2,
"format": "webp",
"quality": 90
}
}' \
-o screenshot.webpCapture a Specific Element
Use selector to capture only a particular DOM element:
curl -X POST https://pixdoc.dev/api/v1/screenshot \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"options": {
"selector": "#hero-section",
"deviceScaleFactor": 2
}
}' \
-o hero.pngDark Mode with Custom CSS
curl -X POST https://pixdoc.dev/api/v1/screenshot \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"options": {
"darkMode": true,
"injectCSS": ".cookie-banner { display: none !important; }"
}
}' \
-o dark-screenshot.pngCommon Patterns
Link Previews
Generate thumbnail previews of URLs for your application:
{
"url": "https://example.com/article",
"options": {
"width": 1200,
"height": 630,
"format": "jpeg",
"quality": 75,
"deviceScaleFactor": 1,
"blockAds": true,
"timeout": 15000
}
}
Visual Regression Testing
Capture screenshots at consistent dimensions for diffing:
{
"url": "https://staging.example.com",
"options": {
"width": 1440,
"height": 900,
"deviceScaleFactor": 1,
"format": "png",
"blockAds": true,
"injectCSS": "* { animation: none !important; transition: none !important; }",
"waitForTimeout": 2000
}
}
Inject CSS to disable animations and transitions for deterministic screenshots in visual regression tests.
Authenticated Pages
Use cookies and extraHeaders to capture pages behind authentication:
{
"url": "https://app.example.com/dashboard",
"options": {
"cookies": [
{ "name": "session_id", "value": "abc123", "domain": "app.example.com" }
],
"extraHeaders": {
"X-Custom-Auth": "token-value"
},
"waitForSelector": ".dashboard-loaded"
}
}
Response
A successful request returns the image as a binary stream.
Response Headers
| Header | Description |
|---|---|
Content-Type | image/png, image/jpeg, or image/webp depending on format |
X-Render-Duration-Ms | Time taken to render, in milliseconds |
X-Renders-Remaining | Number of renders left in your monthly quota |
Error Responses
Errors return JSON with a status code and error details:
{
"error": "INVALID_INPUT",
"message": "Exactly one of 'html' or 'url' must be provided"
}
| Status | Error Code | Meaning |
|---|---|---|
| 400 | INVALID_INPUT | Missing or invalid fields in the request body |
| 401 | UNAUTHORIZED | Invalid or missing API key |
| 429 | RATE_LIMITED | Monthly render limit exceeded |
| 500 | RENDER_FAILED | The renderer encountered an error (e.g., page timeout, DNS failure) |
Email Template Preview
The screenshot endpoint works well for rendering HTML email templates as preview images. Email HTML typically uses table-based layouts with inline CSS, and testing at the correct viewport width is critical for accurate previews.
Recommended Settings
| Setting | Value | Reason |
|---|---|---|
width | 600 | Standard desktop email client width |
width | 320 | Mobile email client width |
format | "png" | Best for crisp text rendering |
fullPage | true | Capture the entire email length |
Example
curl -X POST https://pixdoc.dev/api/v1/screenshot \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<table width=\"600\" cellpadding=\"0\" cellspacing=\"0\" style=\"font-family:Arial,sans-serif\"><tr><td style=\"background:#4f46e5;color:#fff;padding:24px;text-align:center\"><h1>Newsletter</h1></td></tr><tr><td style=\"padding:24px\"><p>Your email content here.</p></td></tr></table>",
"options": {
"width": 600,
"format": "png",
"fullPage": true
}
}' \
-o email-preview.pngTry the free Email Preview Tool to quickly test your HTML email rendering at desktop and mobile widths — no API key needed.
Async Rendering
For high-volume or long-running screenshot jobs, use async mode by setting "async": true. The API returns immediately with a 202 Accepted response and a request_id. Optionally add a webhook_url to have the result delivered to your endpoint, or poll for it using the poll_url.
curl -X POST https://pixdoc.dev/api/v1/screenshot \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"async": true,
"webhook_url": "https://example.com/hooks/render",
"webhook_secret": "whsec_your_secret",
"options": {
"fullPage": true,
"deviceScaleFactor": 2
}
}'This returns a 202 Accepted response with a request_id you can use to poll for status. See the Webhooks documentation for the full setup guide, payload format, and signature verification.
Poll-Only (No Webhook)
Set "async": true without a webhook_url to poll for the result. The response is the same 202 with a request_id — poll GET /api/v1/renders/{request_id} for the result.
curl -X POST https://pixdoc.dev/api/v1/screenshot \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"async": true,
"options": {
"fullPage": true
}
}'Async rendering requires a paid plan (Starter or above).