Everything you need to start capturing screenshots programmatically.
Base URL
https://screenshotapi-api-production.up.railway.appAll API requests require an API key sent via the Authorization header.
Authorization: Bearer YOUR_API_KEYGet your API key by signing up at our pricing page. Your free account includes 100 screenshots per month.
Keep your API key secret. Do not expose it in client-side code. Always make API calls from your server.
/v1/screenshotCapture a screenshot of any public website. Returns the image directly as binary data.
| Parameter | Type | Default | Description |
|---|---|---|---|
urlrequired | string | -- | The URL to capture. Must be a valid HTTP or HTTPS URL. |
width | integer | 1280 | Viewport width in pixels. Min: 320, Max: 3840. |
height | integer | 800 | Viewport height in pixels. Min: 200, Max: 2160. |
format | string | png | Output format: png, jpeg, or webp. |
fullpage | boolean | false | Capture the entire scrollable page. |
quality | integer | 80 | Image quality for JPEG/WebP (1-100). Ignored for PNG. |
wait | integer | 1000 | Additional wait time in ms after page load (0-10000). |
blockads | boolean | false | Block cookie banners and ads before capturing. Removes common consent dialogs, ad slots, and overlay popups. |
output_width | integer | -- | Resize the output image to this width in pixels (min: 16, max: 3840). Great for generating thumbnails. |
output_height | integer | -- | Resize the output image to this height in pixels (min: 16, max: 3840). Maintains aspect ratio when only one dimension is set. |
css | string | -- | Custom CSS to inject before capture. Max 10KB. Example: "header { display: none; }" to hide elements. |
js | string | -- | Custom JavaScript to execute before capture. Max 10KB. Example: "document.querySelector('.popup').remove()" |
wait_for_selector | string | -- | Wait for a CSS selector to appear before capturing (max 10s timeout). Example: "#main-content" |
retries | integer | 1 | Number of retry attempts on transient failures (timeouts, network errors). Min: 0, Max: 3. Set to 0 to disable retries. |
Returns the screenshot as binary image data with the appropriate Content-Type header.
| Header | Description |
|---|---|
Content-Type | image/png, image/jpeg, or image/webp |
Content-Length | Size of the image in bytes |
X-Screenshot-Time-Ms | Time taken to capture the screenshot in milliseconds |
curl "https://screenshotapi-api-production.up.railway.app/v1/screenshot\
?url=https://github.com\
&width=1920&height=1080\
&format=jpeg&quality=90\
&fullpage=true" \
-H "Authorization: Bearer sk_live_abc123" \
-o github.jpeg/v1/screenshotSame endpoint also accepts POST with a JSON body. Useful for complex requests.
curl -X POST "https://screenshotapi-api-production.up.railway.app/v1/screenshot" \
-H "Authorization: Bearer sk_live_abc123" \
-H "Content-Type: application/json" \
-d '{"url":"https://github.com","width":1920,"height":1080,"format":"png","fullPage":true}' \
-o github.png/v1/screenshot/asyncCapture screenshots asynchronously. The API returns immediately with a job ID. You can either poll the status endpoint or provide a callback_url to receive the result via webhook.
When to use async mode: Batch processing, serverless functions with short timeouts, or when you want non-blocking screenshot capture in your application.
| Parameter | Type | Default | Description |
|---|---|---|---|
callback_url | string | -- | URL to POST the result to when the screenshot is complete. Must be a publicly accessible HTTPS endpoint. |
All standard screenshot parameters (url, width, height, format, etc.) are also supported.
{
"id": "job_1710000000_abc12345",
"status": "pending",
"status_url": "/v1/status/job_1710000000_abc12345",
"message": "Screenshot job queued. Poll the status_url or wait for webhook callback."
}/v1/status/:jobIdCheck the status of an async job. Jobs expire after 1 hour.
{
"id": "job_1710000000_abc12345",
"status": "completed",
"created_at": "2026-03-14T10:00:00.000Z",
"completed_at": "2026-03-14T10:00:03.500Z",
"duration_ms": 3500,
"result": {
"content_type": "image/png",
"size_bytes": 245760,
"data_base64": "/9j/4AAQSkZ..."
}
}When a callback_url is provided, the API will POST the result to your endpoint when the screenshot is ready.
{
"id": "job_1710000000_abc12345",
"status": "completed",
"content_type": "image/png",
"size_bytes": 245760,
"duration_ms": 3500,
"data_base64": "/9j/4AAQSkZ..."
}const API_KEY = 'YOUR_API_KEY';
const BASE = 'https://screenshotapi-api-production.up.railway.app';
// 1. Start async job
const res = await fetch(`${BASE}/v1/screenshot/async`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://example.com',
format: 'png',
width: 1920,
height: 1080,
}),
});
const { id, status_url } = await res.json();
console.log('Job started:', id);
// 2. Poll for result
let job;
do {
await new Promise(r => setTimeout(r, 1000));
const status = await fetch(`${BASE}${status_url}`);
job = await status.json();
} while (job.status === 'pending' || job.status === 'processing');
// 3. Save result
if (job.status === 'completed') {
const buffer = Buffer.from(job.result.data_base64, 'base64');
require('fs').writeFileSync('screenshot.png', buffer);
console.log('Done!');
}/v1/pdfGenerate a PDF of any public website. Returns the PDF directly as binary data.
| Parameter | Type | Default | Description |
|---|---|---|---|
urlrequired | string | -- | The URL to convert to PDF. |
format | string | A4 | Paper size: A4, Letter, Legal, Tabloid, A3. |
landscape | boolean | false | Use landscape orientation. |
background | boolean | true | Print background colors and images. |
wait | integer | 1000 | Additional wait time in ms after page load. |
curl "https://screenshotapi-api-production.up.railway.app/v1/pdf\
?url=https://example.com\
&format=A4&landscape=true" \
-H "Authorization: Bearer sk_live_abc123" \
-o page.pdf/v1/usageCheck your current usage and remaining quota.
{
"plan": "pro",
"used": 1523,
"limit": 10000,
"remaining": 8477,
"reset_date": "2026-04-01"
}Errors return JSON with an error field.
| Status | Meaning |
|---|---|
400 | Bad request (missing/invalid parameters) |
401 | Invalid or missing API key |
429 | Rate limit exceeded or monthly quota reached |
504 | Page load timed out (30 second limit) |
500 | Internal server error |
{
"error": "URL parameter is required"
}API requests are rate-limited per API key. Rate limit headers are included in every response.
| Header | Description |
|---|---|
X-RateLimit-Limit | Max requests per minute |
X-RateLimit-Remaining | Remaining requests in current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Screenshot endpoints are limited to 30 requests per minute. Other endpoints are limited to 120 requests per minute.
Our official Node.js SDK makes integration dead simple. Supports CommonJS, ESM, and TypeScript out of the box with zero dependencies.
npm install screenshotapi-nodeconst { ScreenshotAPI } = require('screenshotapi-node');
const client = new ScreenshotAPI('YOUR_API_KEY');
// Capture a screenshot
const buffer = await client.screenshot('https://example.com', {
width: 1920,
height: 1080,
format: 'png',
fullPage: true,
});
require('fs').writeFileSync('screenshot.png', buffer);
// Generate a PDF
const pdf = await client.pdf('https://example.com', {
format: 'A4',
landscape: true,
});
require('fs').writeFileSync('page.pdf', pdf);
// Async screenshot with polling
const result = await client.screenshotAsync('https://example.com', {
format: 'png',
});
console.log('Job ID:', result.id);
// Check status
const status = await client.getStatus(result.id);
console.log('Status:', status.status);
// Check usage
const usage = await client.getUsage();
console.log(`Used ${usage.used}/${usage.limit} screenshots`);| Method | Description |
|---|---|
screenshot(url, options) | Capture a screenshot, returns Buffer |
pdf(url, options) | Generate a PDF, returns Buffer |
screenshotAsync(url, options) | Start async screenshot job |
getStatus(jobId) | Check async job status |
getUsage() | Get current usage and quota |
Full documentation: See the SDK README on GitHub for complete API reference, TypeScript types, and advanced usage.
Our official Python SDK provides a clean, Pythonic interface to the ScreenshotAPI. Zero dependencies -- uses only the Python standard library.
pip install screenshotapifrom screenshotapi import ScreenshotAPI
client = ScreenshotAPI("YOUR_API_KEY")
# Capture a screenshot
data = client.screenshot("https://example.com", width=1920, height=1080, format="png")
with open("screenshot.png", "wb") as f:
f.write(data)
# Generate a PDF
pdf_data = client.pdf("https://example.com", format="A4", landscape=True)
with open("page.pdf", "wb") as f:
f.write(pdf_data)
# Async screenshot
job = client.screenshot_async("https://example.com", format="png")
print(f"Job ID: {job['id']}")
# Check status
status = client.get_status(job["id"])
print(f"Status: {status['status']}")
# Check usage
usage = client.get_usage()
print(f"Used {usage['used']}/{usage['limit']} screenshots")| Method | Description |
|---|---|
screenshot(url, **kwargs) | Capture a screenshot, returns bytes |
pdf(url, **kwargs) | Generate a PDF, returns bytes |
screenshot_async(url, **kwargs) | Start async screenshot job |
get_status(job_id) | Check async job status |
get_usage() | Get current usage and quota |
Full documentation: See the Python SDK README on GitHub for complete API reference and advanced usage.
const fs = require('fs');
async function captureScreenshot(url) {
const response = await fetch(
`https://screenshotapi-api-production.up.railway.app/v1/screenshot?url=${encodeURIComponent(url)}&format=png`,
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error);
}
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync('screenshot.png', buffer);
console.log('Screenshot saved!');
}
captureScreenshot('https://example.com');import requests
API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://screenshotapi-api-production.up.railway.app'
def capture_screenshot(url, output='screenshot.png', **kwargs):
params = {'url': url, 'format': 'png', **kwargs}
headers = {'Authorization': f'Bearer {API_KEY}'}
response = requests.get(
f'{BASE_URL}/v1/screenshot',
params=params,
headers=headers
)
response.raise_for_status()
with open(output, 'wb') as f:
f.write(response.content)
print(f'Screenshot saved to {output}')
print(f'Time: {response.headers.get("X-Screenshot-Time-Ms")}ms')
# Basic screenshot
capture_screenshot('https://example.com')
# Full page, mobile viewport
capture_screenshot(
'https://example.com',
output='mobile.png',
width=375,
height=812,
fullpage='true'
)<?php
$apiKey = 'YOUR_API_KEY';
$url = urlencode('https://example.com');
$ch = curl_init("https://screenshotapi-api-production.up.railway.app/v1/screenshot?url=$url&format=png");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer $apiKey"
]);
$screenshot = curl_exec($ch);
curl_close($ch);
file_put_contents('screenshot.png', $screenshot);
echo "Screenshot saved!\n";Need help? Contact us at support@screenshotapi.dev