Screenshots
The Screenshots API is the core of ScreenshotRun. It lets you capture any website, raw HTML, or Markdown as an image or PDF, then retrieve, list, or delete screenshots you have created. All endpoints require authentication.
This page covers every endpoint. For the full list of capture parameters (viewport, format, device emulation, and more), see Screenshot Options.
How It Works
There are two ways to capture a screenshot:
- Synchronous (Quick Capture) — send a request and get the image back directly. No polling, no waiting. Best for simple integrations where you need the image right away.
- Asynchronous (Create) — send a request and get a screenshot ID back immediately. The screenshot is processed in the background. You can poll for its status or use a webhook to get notified when it is ready. Best for high-volume workloads or when you don't need the image instantly.
Quick Capture
GET /v1/screenshots/capture
POST /v1/screenshots/capture
The simplest way to take a screenshot. The API waits for the capture to finish and returns the image file directly — no polling needed.
Use GET with query parameters for simple requests. Use POST with a JSON body when sending large payloads like html or markdown (GET query strings have length limits).
Both methods accept the same parameters.
Example: GET with query parameters
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&width=1440&format=webp" \
-o screenshot.webp
Example: POST with JSON body
curl -X POST https://api.screenshotrun.com/v1/screenshots/capture \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Hello World</h1><p>Rendered from HTML</p>",
"width": 1200,
"height": 630
}' \
-o screenshot.png
Using in the browser
Because the GET endpoint returns a binary image, you can use it directly in HTML as a link or an image source. Just make sure to use a domain-restricted API key if embedding in client-side code.
<a href="https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&width=1280&format=png">
Take Screenshot
</a>
To get the async JSON response instead (same behavior as POST /v1/screenshots), pass response_type=json.
Create a Screenshot
POST /v1/screenshots
Queues a new screenshot for capture in the background. Returns a 202 Accepted response with the screenshot object in pending status. This is the async method — the screenshot is not ready yet when you get the response.
After creating a screenshot, you can either poll for its status with Get a Screenshot, or set up a webhook to be notified automatically when it completes.
When to use async vs. sync
- Use async (
POST /screenshots) when you are capturing many screenshots, processing them in a queue, or want non-blocking behavior in your application. - Use sync (
GET /capture) when you need the image right away and your use case is simple — a single capture at a time.
Example Request
cURL
curl -X POST https://api.screenshotrun.com/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,
"dark_mode": true
}'
PHP
$response = Http::withToken(env('SCREENSHOT_API_KEY'))
->post('https://api.screenshotrun.com/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://api.screenshotrun.com/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://api.screenshotrun.com/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}`);
Ruby
require "net/http"
require "json"
require "uri"
uri = URI("https://api.screenshotrun.com/v1/screenshots")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer YOUR_API_KEY"
request["Content-Type"] = "application/json"
request.body = {
url: "https://example.com",
width: 1440,
height: 900,
format: "webp",
full_page: true,
dark_mode: true
}.to_json
response = http.request(request)
screenshot = JSON.parse(response.body)["data"]
puts "Screenshot ID: #{screenshot['id']}"
Go
payload := strings.NewReader(`{
"url": "https://example.com",
"width": 1440,
"height": 900,
"format": "webp",
"full_page": true,
"dark_mode": true
}`)
req, _ := http.NewRequest("POST", "https://api.screenshotrun.com/v1/screenshots", payload)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var result struct {
Data struct {
ID string `json:"id"`
} `json:"data"`
}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Printf("Screenshot ID: %s\n", result.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://api.screenshotrun.com/v1/screenshots/550e8400-e29b-41d4-a716-446655440000"
}
}
}
Screenshot Statuses
After you create a screenshot, it moves through these statuses:
| Status | Meaning |
|---|---|
pending | The screenshot is queued and waiting to be processed. |
processing | A browser is loading the page and taking the screenshot right now. |
completed | The screenshot is ready. You can download the image. |
failed | Something went wrong. Check the error field for details. |
Polling for Completion
If you are not using webhooks, you can poll for the screenshot status. Here is a simple polling example in Python:
import time
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.screenshotrun.com/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
For production workloads, use webhooks instead of polling. They are more efficient and give you instant notifications.
Get a Screenshot
GET /v1/screenshots/{id}
Returns the screenshot object with its current status and details. Use this to check whether an async screenshot has finished processing.
Example Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://api.screenshotrun.com/v1/screenshots/550e8400-e29b-41d4-a716-446655440000
Response — Completed
When the screenshot is ready, the response includes full metadata: image dimensions, file size, processing time, and download links.
{
"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://api.screenshotrun.com/v1/screenshots/550e8400-e29b-41d4-a716-446655440000",
"image": "https://api.screenshotrun.com/v1/screenshots/550e8400-e29b-41d4-a716-446655440000/image"
}
}
}
Response — Failed
If something went wrong during capture, the error field tells you what happened. Common causes include page timeouts, invalid URLs, and blocked content.
{
"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://api.screenshotrun.com/v1/screenshots/550e8400-e29b-41d4-a716-446655440000"
}
}
}
Get Screenshot Image
GET /v1/screenshots/{id}/image
Downloads the actual image file. This only works for screenshots with completed status. The response includes the correct Content-Type header for the format you chose (e.g. image/png, image/webp, application/pdf).
Example Request
# Download to file
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://api.screenshotrun.com/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 is not ready yet (status is pending or processing) |
410 Gone | Screenshot image has expired and been deleted (see Image Retention below) |
Image Retention
Screenshots are stored temporarily. After the retention period expires, the image file is automatically deleted. The metadata (status, options, timestamps) stays available through the API, but the image itself returns 410 Gone.
How long your screenshots are kept depends on your plan:
| Plan | Retention |
|---|---|
| Free | 24 hours |
| Starter | 48 hours |
| Pro | 7 days |
| Growth | 30 days |
| Business | 30 days |
Download images as soon as they are ready, or use webhooks to trigger automatic downloads when screenshots complete. You can also create signed URLs to share images without exposing your API key.
List Screenshots
GET /v1/screenshots
Returns a paginated list of your screenshots, newest first. You can filter by status and date range, which is useful for building dashboards or audit logs.
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://api.screenshotrun.com/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://api.screenshotrun.com/v1/screenshots?page=1",
"last": "https://api.screenshotrun.com/v1/screenshots?page=5",
"prev": null,
"next": "https://api.screenshotrun.com/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://api.screenshotrun.com/v1/screenshots",
"per_page": 10,
"to": 10,
"total": 48
}
}
Delete a Screenshot
DELETE /v1/screenshots/{id}
Permanently deletes a screenshot and its image file. This action cannot be undone.
Example Request
curl -X DELETE -H "Authorization: Bearer YOUR_API_KEY" \
https://api.screenshotrun.com/v1/screenshots/550e8400-e29b-41d4-a716-446655440000
Response
Returns 204 No Content on success with an empty body.
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 telling you which feature requires an upgrade. Check your current plan details anytime via GET /v1/account.
| 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 |
geolocation | — | — | — | Yes |
proxy | — | — | — | Yes |
Next Steps
- Screenshot Options — full parameter reference, grouped by category, with examples for every option
- Caching — avoid redundant captures by caching screenshots
- Signed URLs — share screenshots without exposing your API key
- Batch Screenshots — capture up to 100 URLs in a single request
- Webhooks — get notified when screenshots are ready