Screenshots
The Screenshots API allows you to capture, retrieve, list, and delete website screenshots. All endpoints require authentication.
Create a Screenshot
POST /api/v1/screenshots
Queues a new screenshot for capture. Returns a 202 Accepted response with the screenshot object in pending status.
Feature Availability
Some parameters are only available on certain plans. If you use a feature not included in your plan, the API returns a 422 error with a message indicating which feature requires an upgrade.
Note: The table below reflects the current plan configuration. Plan features and limits are managed dynamically and may change over time. Always check your current plan details via GET /api/v1/account for the most up-to-date information.
| Feature / Parameter | Free | Starter | Pro | Business |
|---|---|---|---|---|
url, width, height | Yes | Yes | Yes | Yes |
full_page | Yes | Yes | Yes | Yes |
delay | Yes | Yes | Yes | Yes |
block_cookies | Yes | Yes | Yes | Yes |
selector | Yes | Yes | Yes | Yes |
wait_for_selector | Yes | Yes | Yes | Yes |
omit_background | Yes | Yes | Yes | Yes |
reduced_motion | Yes | Yes | Yes | Yes |
device (mobile/tablet) | — | Yes | Yes | Yes |
retina | — | Yes | Yes | Yes |
block_ads | — | Yes | Yes | Yes |
block_chats | — | Yes | Yes | Yes |
format: pdf | — | Yes | Yes | Yes |
webhook_url | — | Yes | Yes | Yes |
html (HTML rendering) | — | Yes | Yes | Yes |
user_agent | — | Yes | Yes | Yes |
headers, cookies | — | Yes | Yes | Yes |
dark_mode | — | — | Yes | Yes |
css, js | — | — | Yes | Yes |
stealth | — | — | Yes | Yes |
timezone | — | — | Yes | Yes |
extract_metadata | — | — | Yes | Yes |
markdown (Markdown rendering) | — | — | Yes | Yes |
| Batch API | — | — | Yes | Yes |
| Signed URLs | — | Yes | Yes | Yes |
| PDF options (landscape, page size, margins) | — | Yes | Yes | Yes |
| S3 export | — | — | — | Yes |
geolocation | — | — | — | Yes |
proxy | — | — | — | Yes |
Image Retention
Screenshot images are stored temporarily and automatically deleted after the retention period expires. The retention period depends on your current plan and may change if you upgrade or downgrade:
| Plan | Retention |
|---|---|
| Free | 24 hours |
| Starter | 48 hours |
| Pro | 7 days |
| Business | 30 days |
Once expired, the screenshot metadata remains accessible via the API, but the image file returns 410 Gone. Download images promptly or use webhooks to automate downloads upon completion.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Yes* | — | The URL to capture. Must be a valid HTTP or HTTPS URL. Required unless html or markdown is provided. |
html | string | Yes* | — | Raw HTML to render instead of a URL. Max 500,000 characters. Required unless url or markdown is provided. |
markdown | string | Yes* | — | Markdown content to render as a screenshot. Converted to styled HTML automatically. Max 500,000 characters. Required unless url or html is provided. |
width | integer | No | 1280 | Viewport width in pixels. Range: 320–3840. |
height | integer | No | 800 | Viewport height in pixels. Range: 200–2160. |
format | string | No | png | Image format: png, jpeg, webp, avif, tiff, or pdf. |
quality | integer | No | 80 | Image quality for JPEG, WebP, and AVIF formats. Range: 1–100. |
full_page | boolean | No | false | Capture the full scrollable page instead of just the viewport. |
device | string | No | desktop | Device preset: desktop, tablet, or mobile. Sets appropriate viewport and user-agent. |
block_ads | boolean | No | false | Block ads and trackers before capturing. |
block_cookies | boolean | No | true | Block cookie consent banners (OneTrust, CookieBot, etc.) before capturing. Blocks consent scripts, hides banner elements, and attempts to click “Accept” buttons. |
block_chats | boolean | No | false | Block chat widgets (Intercom, Crisp, Tawk, Drift, etc.) before capturing. |
dark_mode | boolean | No | false | Emulate prefers-color-scheme: dark media feature. |
delay | integer | No | 0 | Wait time in seconds before capture (0–10). Useful for pages with animations or lazy-loaded content. |
timeout | integer | No | 30 | Page load timeout in seconds. Range: 5–60. |
css | string | No | — | Custom CSS to inject into the page before capturing. Max 10,000 characters. |
js | string | No | — | Custom JavaScript to execute on the page before capturing. Max 10,000 characters. |
selector | string | No | — | CSS selector of a specific element to capture instead of the full page. Max 500 characters. |
retina | boolean | No | false | Capture at 2x resolution (Retina display). |
resize_width | integer | No | — | Resize the output image to this width in pixels (16–3840). Aspect ratio is preserved. The image will not be enlarged beyond its original size. |
resize_height | integer | No | — | Resize the output image to this height in pixels (16–2160). Aspect ratio is preserved. The image will not be enlarged beyond its original size. |
headers | object | No | — | Custom HTTP headers to send when loading the page. Max 20 headers, each value max 2048 characters. Example: {"X-Custom": "value"} |
cookies | array | No | — | Cookies to set before loading the page. Array of objects with name, value, and optional domain. Max 20 cookies. |
pdf_landscape | boolean | No | false | Generate PDF in landscape orientation. Only applies when format is pdf. |
pdf_page_format | string | No | A4 | PDF page size: A3, A4, A5, Letter, Legal, or Tabloid. |
pdf_margin_top | string | No | 10mm | PDF top margin (e.g. 10mm, 1in, 0). |
pdf_margin_right | string | No | 10mm | PDF right margin. |
pdf_margin_bottom | string | No | 10mm | PDF bottom margin. |
pdf_margin_left | string | No | 10mm | PDF left margin. |
hide_selectors | array | No | — | Array of CSS selectors to hide before capturing (e.g. cookie banners, popups). Max 20 selectors. Example: [".cookie-banner", "#popup"] |
click_selector | string | No | — | CSS selector of an element to click before capturing. Useful for dismissing modals or expanding content. Max 500 characters. |
scroll_to | string | No | — | CSS selector of an element to scroll into view before capturing. Max 500 characters. |
cache_ttl | integer | No | 0 | Cache duration in seconds (0–86400). If a matching screenshot was captured within this period, it is returned immediately without re-rendering. |
wait_for_selector | string | No | — | CSS selector to wait for before capturing. Useful for SPAs and dynamically loaded content. Waits up to 10 seconds. Max 500 characters. |
omit_background | boolean | No | false | Capture with transparent background (PNG and WebP only). Useful for logos and UI elements. |
reduced_motion | boolean | No | false | Emulate prefers-reduced-motion: reduce. Disables CSS animations and transitions for cleaner captures. |
stealth | boolean | No | false | Enable stealth mode to bypass bot detection. Hides automation signals (webdriver, plugins, WebGL, etc.). |
user_agent | string | No | — | Custom User-Agent string. Overrides the device preset User-Agent. Max 500 characters. |
timezone | string | No | — | IANA timezone for the browser context (e.g. America/New_York, Europe/Berlin). Affects Date and Intl APIs. |
geolocation | object | No | — | Emulate browser geolocation. Object with latitude (-90 to 90), longitude (-180 to 180), and optional accuracy (meters). |
proxy | string | No | — | HTTP/SOCKS proxy URL for the request (e.g. http://user:pass@proxy:8080). A dedicated browser is launched per proxy request. |
extract_metadata | boolean | No | false | Extract page metadata (title, description, Open Graph tags, Twitter Card, favicon URL) and include in the response. |
webhook_url | string | No | — | URL to receive a POST notification when the screenshot is ready. See Webhooks. |
Note: You can specify resize_width, resize_height, or both. When both are provided, the image fits inside the given dimensions while maintaining aspect ratio. Resize only applies to image formats (not PDF).
Note: url, html, and markdown are mutually exclusive — provide one of them.
Example Request
cURL
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"width": 1440,
"height": 900,
"format": "webp",
"full_page": true,
"device": "desktop",
"dark_mode": true
}'
PHP
$response = Http::withToken(env('SCREENSHOT_API_KEY'))
->post('https://screenshotrun.com/api/v1/screenshots', [
'url' => 'https://example.com',
'width' => 1440,
'height' => 900,
'format' => 'webp',
'full_page' => true,
'dark_mode' => true,
]);
$screenshot = $response->json('data');
echo "Screenshot ID: " . $screenshot['id'];
Python
import requests
response = requests.post(
"https://screenshotrun.com/api/v1/screenshots",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"url": "https://example.com",
"width": 1440,
"height": 900,
"format": "webp",
"full_page": True,
"dark_mode": True,
}
)
screenshot = response.json()["data"]
print(f"Screenshot ID: {screenshot['id']}")
JavaScript (Node.js)
const response = await fetch("https://screenshotrun.com/api/v1/screenshots", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://example.com",
width: 1440,
height: 900,
format: "webp",
full_page: true,
dark_mode: true,
}),
});
const { data } = await response.json();
console.log(`Screenshot ID: ${data.id}`);
Response (202 Accepted)
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"url": "https://example.com",
"options": {
"width": 1440,
"height": 900,
"format": "webp",
"quality": 80,
"full_page": true,
"device": "desktop",
"block_ads": false,
"block_cookies": true,
"dark_mode": true,
"delay": 0,
"timeout": 30,
"retina": false
},
"estimated_time": 5,
"created_at": "2026-03-09T10:30:00.000000Z",
"links": {
"self": "https://screenshotrun.com/api/v1/screenshots/550e8400-e29b-41d4-a716-446655440000"
}
}
}
Create a Screenshot (GET)
GET /api/v1/screenshots/capture
Alternative to the POST endpoint — creates a screenshot using query parameters instead of a JSON body. Accepts the same parameters as the POST endpoint. Returns a 202 Accepted response.
This is useful for simple integrations, testing in the browser address bar, or embedding screenshot URLs directly in HTML.
Example Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://screenshotrun.com/api/v1/screenshots/capture?url=https://example.com&width=1440&format=webp&full_page=true"
Parameters are passed as query string instead of JSON body. All parameters from the POST endpoint are supported.
Browser / HTML
<a href="https://screenshotrun.com/api/v1/screenshots/capture?url=https://example.com&width=1280&format=png">
Take Screenshot
</a>
The response format is identical to the POST endpoint.
Get a Screenshot
GET /api/v1/screenshots/{id}
Returns the screenshot object with its current status and details.
Example Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://screenshotrun.com/api/v1/screenshots/550e8400-e29b-41d4-a716-446655440000
Response — Completed
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"url": "https://example.com",
"options": {
"width": 1440,
"height": 900,
"format": "webp",
"quality": 80,
"full_page": true,
"device": "desktop",
"block_ads": false,
"block_cookies": true,
"dark_mode": true,
"delay": 0,
"timeout": 30,
"retina": false
},
"file_size": 245760,
"mime_type": "image/webp",
"width": 1440,
"height": 3200,
"processing_time_ms": 3450,
"completed_at": "2026-03-09T10:30:05.000000Z",
"expires_at": "2026-04-09T10:30:05.000000Z",
"created_at": "2026-03-09T10:30:00.000000Z",
"links": {
"self": "https://screenshotrun.com/api/v1/screenshots/550e8400-e29b-41d4-a716-446655440000",
"image": "https://screenshotrun.com/api/v1/screenshots/550e8400-e29b-41d4-a716-446655440000/image"
}
}
}
Response — Failed
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "failed",
"url": "https://example.com",
"options": { ... },
"error": {
"message": "Page load timed out after 30 seconds.",
"code": "TIMEOUT"
},
"created_at": "2026-03-09T10:30:00.000000Z",
"links": {
"self": "https://screenshotrun.com/api/v1/screenshots/550e8400-e29b-41d4-a716-446655440000"
}
}
}
Get Screenshot Image
GET /api/v1/screenshots/{id}/image
Returns the binary image file. Only available for screenshots with completed status.
Example Request
# Download to file
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://screenshotrun.com/api/v1/screenshots/550e8400-.../image \
-o screenshot.webp
Responses
| Status | Description |
|---|---|
200 OK | Image file with appropriate Content-Type header (image/png, image/jpeg, image/webp, image/avif, image/tiff, or application/pdf) |
404 Not Found | Screenshot not ready yet (status is pending or processing) |
410 Gone | Screenshot image has expired and is no longer available |
List Screenshots
GET /api/v1/screenshots
Returns a paginated list of your screenshots, sorted by creation date (newest first).
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
per_page | integer | 20 | Results per page (max 100) |
status | string | — | Filter by status: pending, processing, completed, failed |
sort_by | string | created_at | Sort field |
sort_dir | string | desc | Sort direction: asc or desc |
date_from | string | — | Filter screenshots created after this date (ISO 8601) |
date_to | string | — | Filter screenshots created before this date (ISO 8601) |
Example Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://screenshotrun.com/api/v1/screenshots?status=completed&per_page=10&sort_dir=desc"
Response
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"url": "https://example.com",
"options": { ... },
"file_size": 245760,
"mime_type": "image/webp",
"width": 1440,
"height": 3200,
"processing_time_ms": 3450,
"completed_at": "2026-03-09T10:30:05.000000Z",
"expires_at": "2026-04-09T10:30:05.000000Z",
"created_at": "2026-03-09T10:30:00.000000Z",
"links": {
"self": "...",
"image": "..."
}
}
],
"links": {
"first": "https://screenshotrun.com/api/v1/screenshots?page=1",
"last": "https://screenshotrun.com/api/v1/screenshots?page=5",
"prev": null,
"next": "https://screenshotrun.com/api/v1/screenshots?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 5,
"links": [
{"url": null, "label": "« Previous", "page": null, "active": false},
{"url": "...?page=1", "label": "1", "page": 1, "active": true},
{"url": "...?page=2", "label": "2", "page": 2, "active": false},
{"url": "...?page=2", "label": "Next »", "page": 2, "active": false}
],
"path": "https://screenshotrun.com/api/v1/screenshots",
"per_page": 10,
"to": 10,
"total": 48
}
}
Delete a Screenshot
DELETE /api/v1/screenshots/{id}
Permanently deletes a screenshot and its associated image file. This action cannot be undone.
Example Request
curl -X DELETE -H "Authorization: Bearer YOUR_API_KEY" \
https://screenshotrun.com/api/v1/screenshots/550e8400-e29b-41d4-a716-446655440000
Response
Returns 204 No Content on success with an empty body.
Common Use Cases
Capture a mobile screenshot
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"device": "mobile",
"format": "png"
}'
Full-page screenshot in dark mode
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"full_page": true,
"dark_mode": true,
"format": "webp"
}'
Screenshot with delay (wait for animations)
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"delay": 3
}'
Screenshot with resize (thumbnail)
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"resize_width": 320
}'
This captures a full-size screenshot and then resizes it to 320px wide (height auto-calculated to preserve aspect ratio). Useful for generating thumbnails or previews.
Quick capture via GET
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://screenshotrun.com/api/v1/screenshots/capture?url=https://example.com&format=jpeg&quality=60&resize_width=640"
Screenshot with webhook notification
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"webhook_url": "https://yourapp.com/webhooks/screenshot"
}'
Poll until completed (Python)
import time
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://screenshotrun.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
# Create screenshot
response = requests.post(
f"{BASE_URL}/screenshots",
headers=headers,
json={"url": "https://example.com"}
)
screenshot_id = response.json()["data"]["id"]
# Poll until ready
while True:
status_response = requests.get(
f"{BASE_URL}/screenshots/{screenshot_id}",
headers=headers,
)
data = status_response.json()["data"]
if data["status"] == "completed":
# Download the image
image_response = requests.get(
f"{BASE_URL}/screenshots/{screenshot_id}/image",
headers=headers,
)
with open("screenshot.png", "wb") as f:
f.write(image_response.content)
print("Screenshot saved!")
break
elif data["status"] == "failed":
print(f"Failed: {data['error']['message']}")
break
time.sleep(2) # Wait 2 seconds before next poll
Screenshot with custom headers and cookies
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/dashboard",
"headers": {
"X-Custom-Auth": "token123",
"Accept-Language": "de-DE"
},
"cookies": [
{"name": "session_id", "value": "abc123", "domain": "example.com"},
{"name": "theme", "value": "dark"}
]
}'
HTML to screenshot
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<html><body style=\"padding:40px;font-family:sans-serif\"><h1>Hello World</h1><p>Rendered from raw HTML</p></body></html>",
"width": 800,
"height": 600
}'
When using html, you do not need to provide a url. The HTML is rendered directly in the browser. This is useful for generating images from templates, invoices, reports, or any dynamic content.
PDF with custom options
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/report",
"format": "pdf",
"pdf_landscape": true,
"pdf_page_format": "A3",
"pdf_margin_top": "20mm",
"pdf_margin_bottom": "20mm",
"pdf_margin_left": "15mm",
"pdf_margin_right": "15mm"
}'
Hide elements before capture
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"hide_selectors": [".cookie-banner", "#newsletter-popup", ".ads-container"]
}'
Elements matching the given CSS selectors are hidden (display: none) before the screenshot is taken. Useful for removing cookie consent banners, popups, ads, or any distracting UI elements.
Click before capture
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"click_selector": "#accept-cookies"
}'
Clicks the element matching the selector before taking the screenshot. Useful for dismissing modals, accepting cookie consent, or triggering UI state changes.
Scroll to element
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"scroll_to": "#pricing-section"
}'
Scrolls the page to bring the element into view before capturing. Combine with selector to capture a specific section of the page.
Cached screenshot
curl -X POST https://screenshotrun.com/api/v1/screenshots \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"cache_ttl": 3600
}'
If a screenshot of the same URL with the same options was captured within the last 3600 seconds (1 hour), the existing screenshot is returned immediately without re-rendering. This saves processing time and API credits. Set cache_ttl to 0 (default) to always capture a fresh screenshot.
Batch Screenshots
POST /api/v1/screenshots/batch
Create multiple screenshots in a single API call. All screenshots share the same options but capture different URLs. Returns a 202 Accepted response with an array of screenshot objects.
Requires: The batch feature on your plan.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
urls | array | Yes | Array of URLs to capture. Min 1, max 100. |
| All other parameters from the single screenshot endpoint are supported (width, height, format, etc.). | |||
Example Request
curl -X POST https://screenshotrun.com/api/v1/screenshots/batch \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://example.com",
"https://example.org",
"https://example.net"
],
"width": 1440,
"format": "webp",
"full_page": true
}'
Response (202 Accepted)
{
"data": [
{
"id": "550e8400-...",
"status": "pending",
"url": "https://example.com",
"options": { ... },
"created_at": "2026-03-09T10:30:00.000000Z",
"links": { "self": "..." }
},
{
"id": "660f9500-...",
"status": "pending",
"url": "https://example.org",
"options": { ... },
"created_at": "2026-03-09T10:30:00.000000Z",
"links": { "self": "..." }
},
{
"id": "770a0600-...",
"status": "pending",
"url": "https://example.net",
"options": { ... },
"created_at": "2026-03-09T10:30:00.000000Z",
"links": { "self": "..." }
}
],
"total": 3
}
Each screenshot is processed independently. Poll each one by its id or use webhook_url to be notified when each is ready.
Signed URLs
POST /api/v1/screenshots/{id}/signed-url
Generate an HMAC-signed URL to share a completed screenshot image without requiring an API key. Useful for embedding images in emails, sharing with clients, or displaying in public web pages.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
expires_in | integer | 60 | Expiration time in minutes. Range: 1–43200 (30 days). Pass 0 for a permanent URL. |
Example Request
# Generate a signed URL that expires in 24 hours
curl -X POST https://screenshotrun.com/api/v1/screenshots/550e8400-.../signed-url \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"expires_in": 1440}'
Response
{
"data": {
"url": "https://screenshotrun.com/api/v1/screenshots/550e8400-.../signed-image?expires=1741520400&signature=abc123...",
"expires_at": "2026-03-10T10:30:00+00:00"
}
}
The signed URL can be opened in any browser or used in <img> tags without authentication. Once expired, the URL returns 403 Forbidden.
Example — Permanent signed URL
curl -X POST https://screenshotrun.com/api/v1/screenshots/550e8400-.../signed-url \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"expires_in": 0}'
Permanent URLs remain valid as long as the screenshot image exists (until the retention period ends).