# ScreenshotRun > Screenshot API for developers — capture pixel-perfect screenshots of any website, HTML, or Markdown via a simple HTTP API. ScreenshotRun is a cloud-based screenshot API that lets developers programmatically capture full-page screenshots, generate PDFs, convert HTML to images, and more. It supports 6 image formats (PNG, JPEG, WebP, AVIF, TIFF, PDF), device emulation, dark mode, stealth mode, custom CSS/JS injection, webhooks, and batch capture. Authentication is via Bearer token. Free tier available with 200 screenshots/month. --- ## Getting Started ### 1. Create an Account Sign up at [screenshotrun.com](https://screenshotrun.com/register) — no credit card required. The free plan includes 200 screenshots per month. ### 2. Get Your API Key After signing in, go to [Dashboard > API Keys](https://screenshotrun.com/dashboard/api-keys) and create a new key. The key is shown only once — copy it immediately. ### 3. Take Your First Screenshot ```bash curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&format=png" \ -o screenshot.png ``` That's it. The API returns the screenshot image directly. --- ## Authentication All API requests require a Bearer token in the `Authorization` header: ``` Authorization: Bearer sk_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789ab ``` **Key format:** `sk_live_` prefix followed by 40 alphanumeric characters. **Important:** - API keys are account-bound — all screenshots count toward your plan quota - Keys can be revoked instantly from the dashboard - Optional domain restriction available (checks Origin/Referer headers) - Never expose API keys in client-side code without domain restrictions --- ## API Endpoints **Base URL:** `https://api.screenshotrun.com/v1` ### Capture Screenshot (Sync) ``` GET /v1/screenshots/capture POST /v1/screenshots/capture ``` Takes a screenshot and returns the image file directly. Best for simple use cases. **Example:** ```bash curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&format=webp&full_page=true" \ -o screenshot.webp ``` ### Create Screenshot (Async) ``` POST /v1/screenshots ``` Queues a screenshot for processing. Returns immediately with a screenshot ID (HTTP 202). **Example:** ```bash 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", "format": "webp", "full_page": true, "dark_mode": true }' ``` **Response (202 Accepted):** ```json { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "pending", "url": "https://example.com", "options": { "width": 1280, "height": 800, "format": "webp", "full_page": true, "dark_mode": true }, "created_at": "2026-03-09T10:30:00.000000Z" } } ``` ### Get Screenshot Status ``` GET /v1/screenshots/{id} ``` Returns screenshot metadata and current status. **Statuses:** `pending` → `processing` → `completed` | `failed` ### Download Screenshot Image ``` GET /v1/screenshots/{id}/image ``` Returns the screenshot image file. Only available after status is `completed`. Returns 410 Gone if retention period has expired. ### List Screenshots ``` GET /v1/screenshots ``` Paginated list of your screenshots. Supports filtering by status and date range. Max 100 per page (default 20). ### Batch Capture ``` POST /v1/screenshots/batch ``` Capture 1–100 URLs in a single request. Common options apply to all URLs. Pro plan and above. **Example:** ```bash curl -X POST https://api.screenshotrun.com/v1/screenshots/batch \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "urls": ["https://example.com", "https://example.org"], "format": "webp", "full_page": true }' ``` ### Generate Signed URL ``` POST /v1/screenshots/{id}/signed-url ``` Create a temporary shareable URL that doesn't require an API key. Default expiry: 60 minutes. Pass `expires_in=0` for permanent URL. ### Delete Screenshot ``` DELETE /v1/screenshots/{id} ``` Permanently delete a screenshot and its metadata. Returns 204 No Content. ### Account Info ``` GET /v1/account ``` Returns user info, current plan, and subscription details. ### Usage Statistics ``` GET /v1/account/usage ``` Current billing period usage: screenshots used vs. limit, reset date. --- ## All API Parameters ### Source (one required) | Parameter | Type | Description | |-----------|------|-------------| | `url` | string (max 2048) | HTTP/HTTPS URL to capture | | `html` | string (max 500,000) | Raw HTML to render as screenshot | | `markdown` | string (max 500,000) | Markdown content to render (converted to styled HTML) | ### Viewport & Device | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `width` | integer | 1280 | Viewport width in pixels (320–3840) | | `height` | integer | 800 | Viewport height in pixels (200–2160) | | `device` | string | "desktop" | Device preset: `desktop`, `mobile` (375x812), `tablet` (768x1024) | | `retina` | boolean | false | Capture at 2x resolution | ### Image Output | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `format` | string | "png" | Output format: `png`, `jpeg`, `webp`, `avif`, `tiff`, `pdf` | | `quality` | integer | 80 | Compression quality for JPEG/WebP/AVIF (1–100) | | `resize_width` | integer | — | Resize output width maintaining aspect ratio (16–3840) | | `resize_height` | integer | — | Resize output height maintaining aspect ratio (16–2160) | ### PDF Options | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `pdf_landscape` | boolean | false | Landscape orientation | | `pdf_page_format` | string | "A4" | Page size: `A3`, `A4`, `A5`, `Letter`, `Legal`, `Tabloid` | | `pdf_margin_top` | string | "10mm" | Top margin (CSS units: "10mm", "1in", "0") | | `pdf_margin_right` | string | "10mm" | Right margin | | `pdf_margin_bottom` | string | "10mm" | Bottom margin | | `pdf_margin_left` | string | "10mm" | Left margin | ### Page Loading & Timing | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `delay` | integer | 0 | Wait before capture in seconds (0–10) | | `timeout` | integer | 30 | Page load timeout in seconds (5–60) | | `wait_for_selector` | string | — | CSS selector to wait for before capture (max 500 chars) | | `full_page` | boolean | false | Capture entire scrollable page vs. viewport only | ### Element Selection & Interaction | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `selector` | string | — | CSS selector of specific element to capture | | `click_selector` | string | — | CSS selector of element to click before capture | | `scroll_to` | string | — | CSS selector to scroll into view before capture | | `hide_selectors` | array | — | CSS selectors to hide before capture (max 20 items) | ### Custom Injection | Parameter | Type | Description | |-----------|------|-------------| | `css` | string (max 10,000) | Custom CSS to inject into page | | `js` | string (max 10,000) | Custom JavaScript to execute on page | | `headers` | object (max 20) | Custom HTTP headers for page request | | `cookies` | array (max 20) | Cookies to set: `[{name, value, domain?}]` | ### Blocking & Filtering | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `block_cookies` | boolean | true | Block cookie consent banners (OneTrust, CookieBot, etc.) | | `block_ads` | boolean | false | Block ads and trackers | | `block_chats` | boolean | false | Block chat widgets (Intercom, Crisp, Tawk, Drift) | ### Browser Emulation | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `dark_mode` | boolean | false | Emulate `prefers-color-scheme: dark` | | `reduced_motion` | boolean | false | Emulate `prefers-reduced-motion: reduce` | | `user_agent` | string | — | Custom User-Agent string | | `stealth` | boolean | false | Enable stealth mode to bypass bot detection | | `timezone` | string | — | Browser timezone (IANA format, e.g. "America/New_York") | | `geolocation` | object | — | Emulate location: `{latitude, longitude, accuracy?}` (Business+) | | `proxy` | string | — | HTTP/SOCKS proxy URL (Business+) | ### Advanced | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `extract_metadata` | boolean | false | Extract page title, description, OG tags, Twitter Card, favicon | | `cache_ttl` | integer | 0 | Cache duration in seconds (0–86400). Returns cached result if available | | `omit_background` | boolean | false | Transparent background (PNG/WebP only) | | `webhook_url` | string | — | HTTPS URL to notify when screenshot completes | | `response_type` | string | varies | `"json"` or `"image"`. Capture endpoint defaults to "image", create defaults to "json" | --- ## Webhooks Include `webhook_url` in your screenshot request to receive async notifications. **Requirements:** - Must be an HTTPS endpoint - Must accept POST with JSON body - Must respond with 2xx within 30 seconds ### Events **screenshot.completed** ```json { "event": "screenshot.completed", "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "url": "https://example.com", "options": {}, "file_size": 245760, "mime_type": "image/png", "width": 1280, "height": 800, "processing_time_ms": 3450, "image_url": "https://api.screenshotrun.com/v1/screenshots/550e8400-.../image", "created_at": "2026-03-09T10:30:00.000000Z", "completed_at": "2026-03-09T10:30:05.000000Z" }, "sent_at": "2026-03-09T10:30:05.500000Z" } ``` **screenshot.failed** ```json { "event": "screenshot.failed", "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "failed", "url": "https://example.com", "error": { "message": "Page load timed out after 30 seconds.", "code": "TIMEOUT" }, "created_at": "2026-03-09T10:30:00.000000Z" }, "sent_at": "2026-03-09T10:30:35.000000Z" } ``` ### Webhook Handler Examples **Node.js (Express):** ```javascript app.post('/webhook/screenshot', (req, res) => { const { event, data } = req.body; if (event === 'screenshot.completed') { console.log(`Screenshot ready: ${data.image_url}`); } res.sendStatus(200); }); ``` **Python (Flask):** ```python @app.route('/webhook/screenshot', methods=['POST']) def screenshot_webhook(): payload = request.get_json() if payload['event'] == 'screenshot.completed': print(f"Screenshot ready: {payload['data']['image_url']}") return '', 200 ``` --- ## Integration Examples ### Node.js ```javascript const API_KEY = 'YOUR_API_KEY'; const BASE_URL = 'https://api.screenshotrun.com/v1'; // Sync capture — returns image directly const response = await fetch( `${BASE_URL}/screenshots/capture?url=https://example.com&format=webp&full_page=true`, { headers: { 'Authorization': `Bearer ${API_KEY}` } } ); const buffer = await response.arrayBuffer(); fs.writeFileSync('screenshot.webp', Buffer.from(buffer)); // Async capture const result = await fetch(`${BASE_URL}/screenshots`, { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ url: 'https://example.com', format: 'png', full_page: true }) }); const { data } = await result.json(); console.log(`Screenshot ID: ${data.id}, Status: ${data.status}`); ``` ### Python ```python import requests API_KEY = 'YOUR_API_KEY' BASE_URL = 'https://api.screenshotrun.com/v1' headers = {'Authorization': f'Bearer {API_KEY}'} # Sync capture response = requests.get(f'{BASE_URL}/screenshots/capture', headers=headers, params={ 'url': 'https://example.com', 'format': 'webp', 'full_page': True }) with open('screenshot.webp', 'wb') as f: f.write(response.content) # Async capture response = requests.post(f'{BASE_URL}/screenshots', headers=headers, json={ 'url': 'https://example.com', 'format': 'png', 'full_page': True }) data = response.json()['data'] print(f"Screenshot ID: {data['id']}, Status: {data['status']}") ``` ### PHP ```php $apiKey = 'YOUR_API_KEY'; // Using Laravel HTTP Client $response = Http::withToken($apiKey) ->get('https://api.screenshotrun.com/v1/screenshots/capture', [ 'url' => 'https://example.com', 'format' => 'webp', 'full_page' => true, ]); Storage::put('screenshot.webp', $response->body()); // Async capture $response = Http::withToken($apiKey) ->post('https://api.screenshotrun.com/v1/screenshots', [ 'url' => 'https://example.com', 'format' => 'png', 'full_page' => true, ]); $data = $response->json('data'); ``` ### cURL ```bash # Sync capture — save image directly curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&format=png&full_page=true" \ -o screenshot.png # Async capture — get JSON with screenshot ID 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", "format": "webp", "full_page": true}' # Check status curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.screenshotrun.com/v1/screenshots/SCREENSHOT_ID" # Download completed screenshot curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.screenshotrun.com/v1/screenshots/SCREENSHOT_ID/image" \ -o screenshot.png ``` ### Go ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { client := &http.Client{} req, _ := http.NewRequest("GET", "https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&format=png", nil) req.Header.Set("Authorization", "Bearer YOUR_API_KEY") resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() file, _ := os.Create("screenshot.png") defer file.Close() io.Copy(file, resp.Body) fmt.Println("Screenshot saved") } ``` ### Java ```java import java.net.http.*; import java.nio.file.*; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&format=png")) .header("Authorization", "Bearer YOUR_API_KEY") .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); Files.write(Path.of("screenshot.png"), response.body()); ``` ### Ruby ```ruby require 'net/http' require 'uri' require 'json' api_key = 'YOUR_API_KEY' uri = URI("https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&format=png") request = Net::HTTP::Get.new(uri) request['Authorization'] = "Bearer #{api_key}" response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end File.binwrite('screenshot.png', response.body) ``` --- ## Pricing | Plan | Price | Screenshots/mo | Rate Limit | Retention | Overage | |------|-------|----------------|------------|-----------|---------| | **Free** | $0 | 200 | 5/min | 24 hours | N/A | | **Starter** | $9/mo | 3,000 | 15/min | 48 hours | $0.009/ea | | **Pro** | $29/mo | 15,000 | 40/min | 7 days | $0.006/ea | | **Growth** | $79/mo | 50,000 | 100/min | 30 days | $0.004/ea | | **Business** | $119/mo | 100,000 | 150/min | 30 days | $0.003/ea | Annual billing saves ~17% (pay for 10 months, get 12). ### Feature Availability by Plan | Feature | Free | Starter | Pro | Growth | Business | |---------|------|---------|-----|--------|----------| | Basic capture (url, width, height) | yes | yes | yes | yes | yes | | full_page, delay, selector | yes | yes | yes | yes | yes | | block_cookies, wait_for_selector | yes | yes | yes | yes | yes | | omit_background, reduced_motion | yes | yes | yes | yes | yes | | Mobile/tablet, retina | — | yes | yes | yes | yes | | block_ads, block_chats | — | yes | yes | yes | yes | | PDF, HTML-to-image | — | yes | yes | yes | yes | | Webhooks, custom headers/cookies | — | yes | yes | yes | yes | | Dark mode, custom CSS/JS | — | — | yes | yes | yes | | Signed URLs, stealth, timezone | — | — | yes | yes | yes | | Metadata extraction, markdown | — | — | yes | yes | yes | | Batch API | — | — | yes | yes | yes | | Geolocation, proxy | — | — | — | yes | yes | | Priority support | — | — | — | — | yes | --- ## Features ### Full Page Screenshot Capture the entire scrollable page from top to bottom, not just the visible viewport. Set `full_page=true`. Handles lazy-loaded images, sticky headers, and infinite scroll content. ### Wait for Selector & Delay Wait for dynamic content to load before capturing. Use `wait_for_selector` for SPAs that render content asynchronously, or `delay` for animations. Combine both for complex pages. ### Block Cookie Banners Automatically hide GDPR/cookie consent popups from screenshots. Set `block_cookies=true` (enabled by default). Supports OneTrust, CookieBot, Cookielaw, and dozens of other consent managers. ### Block Ads & Chat Widgets Remove ads, trackers, and chat widgets (Intercom, Crisp, Tawk.to, Drift) from screenshots for clean captures. Use `block_ads=true` and `block_chats=true`. ### Custom Viewport & Device Emulation Set any viewport resolution with `width` and `height`, or use device presets (`desktop`, `mobile`, `tablet`) that set appropriate dimensions and user-agent strings. Enable `retina=true` for 2x resolution. ### Website to PDF Convert any webpage to PDF with `format=pdf`. Control orientation (`pdf_landscape`), page size (`pdf_page_format`: A3, A4, A5, Letter, Legal, Tabloid), and margins (`pdf_margin_top/right/bottom/left`). ### HTML to Image Render raw HTML/CSS/JS into screenshots without needing a live URL. Pass HTML via the `html` parameter or Markdown via `markdown`. Perfect for generating images from templates, reports, or email designs. ### Dark Mode Capture websites as they appear in dark mode by emulating `prefers-color-scheme: dark`. Set `dark_mode=true`. Works with any website that supports CSS dark mode media queries. ### Image Format & Quality Choose from 6 output formats: PNG (lossless), JPEG (smallest for photos), WebP (modern, great compression), AVIF (next-gen), TIFF (archival), PDF (document). Control compression with `quality` (1–100). ### MCP Server Model Context Protocol integration that allows AI agents (Claude, GPT, etc.) to autonomously capture screenshots as part of their workflows. Install the MCP server and AI agents can capture, analyze, and use screenshots. ### Webhooks Get notified when screenshots are ready instead of polling. Include `webhook_url` in your request. Receives `screenshot.completed` and `screenshot.failed` events with full metadata. ### Stealth Mode Bypass bot detection systems with `stealth=true`. Applies patches to avoid headless browser fingerprinting. Useful for sites that block automated access. ### Element Screenshot Capture a specific HTML element instead of the full page. Use `selector` with a CSS selector (e.g., `selector=.hero-section`). Only the matched element is captured and cropped. ### Click Before Capture Click an element before taking the screenshot with `click_selector`. Useful for opening dropdown menus, accepting dialogs, or triggering state changes. ### Custom CSS & JS Injection Inject custom CSS (`css` parameter) to restyle pages or hide elements. Execute custom JavaScript (`js` parameter) to modify DOM, fill forms, or trigger interactions before capture. ### Metadata Extraction Extract page metadata alongside the screenshot with `extract_metadata=true`. Returns page title, meta description, Open Graph tags, Twitter Card data, and favicon URL. ### Caching Cache screenshots for up to 24 hours with `cache_ttl` (in seconds). Subsequent requests with the same URL and parameters return the cached result instantly, saving quota and time. ### Geolocation & Proxy Emulate geographic location with `geolocation` (latitude/longitude) or route requests through a proxy with `proxy` (HTTP/SOCKS). Available on Growth and Business plans. ### Transparent Background Capture screenshots with a transparent background using `omit_background=true`. Works with PNG and WebP formats. Useful for capturing elements without page background. --- ## Use Cases ### Link Previews & Website Thumbnails Generate live website thumbnail previews for link directories, bookmark managers, search results, and social sharing. Automate with the API to keep thumbnails fresh. ### Visual Regression Testing Compare screenshots across deployments to catch unintended visual changes. Integrate with CI/CD pipelines (GitHub Actions, GitLab CI) for automated visual testing. ### AI Agent Vision Give AI agents the ability to see and analyze web pages. Use the MCP Server for direct integration with Claude and other AI assistants, or call the API from autonomous agents. ### Website Change Monitoring Schedule periodic screenshots to detect visual changes on competitor websites, regulatory pages, or your own sites. Compare images programmatically to alert on differences. ### Website Archiving Create visual archives of web pages as screenshots or PDFs. Preserve the visual state of content that may change or disappear. Full-page capture ensures complete records. ### OG Image Generation Generate Open Graph and social media preview images from HTML templates. Design templates with HTML/CSS, render them via the `html` parameter, and serve as OG images. ### PDF Invoice Generation Convert HTML invoice templates to professional PDFs using `format=pdf`. Control page format, margins, and orientation. Generate invoices, receipts, and reports programmatically. --- ## Error Codes | HTTP Status | Description | |-------------|-------------| | 400 | Bad Request — invalid parameters | | 401 | Unauthorized — missing or invalid API key | | 403 | Forbidden — feature not available on your plan | | 404 | Not Found — screenshot ID doesn't exist | | 410 | Gone — screenshot image expired (retention period passed) | | 422 | Unprocessable Entity — validation errors | | 429 | Too Many Requests — rate limit exceeded | | 500 | Internal Server Error | --- ## Links - Website: [https://screenshotrun.com](https://screenshotrun.com) - API Base URL: `https://api.screenshotrun.com/v1` - Documentation: [https://screenshotrun.com/docs/getting-started](https://screenshotrun.com/docs/getting-started) - Dashboard: [https://screenshotrun.com/dashboard](https://screenshotrun.com/dashboard) - Pricing: [https://screenshotrun.com/pricing](https://screenshotrun.com/pricing) - Blog: [https://screenshotrun.com/blog](https://screenshotrun.com/blog) - Contact: [https://screenshotrun.com/contact-us](https://screenshotrun.com/contact-us)