# ScreenshotEngine API documentation Capture public website URLs as PNG, JPEG, WebP, PDF, or scrolling WebM video. Endpoint: https://api.screenshotengine.com/v1/screenshot Use POST with Authorization: Bearer YOUR_API_KEY and a JSON body, or GET with an api_key query parameter. Successful requests return binary file bytes, not JSON. - [Screenshot API quickstart](https://www.screenshotengine.com/docs/quickstart): Make your first ScreenshotEngine API request with cURL. Get an API key, capture a full-page PNG, and save the binary response. - [API keys and authentication](https://www.screenshotengine.com/docs/authentication): Authenticate ScreenshotEngine GET and POST requests, store API keys securely, and understand the difference between query and Bearer authentication. - [Screenshot API parameter reference](https://www.screenshotengine.com/docs/parameters): Compare GET and POST options for screenshots, PDF, WebM video, viewport sizes, CSS selectors, delays, watermarking, and cache control. - [Screenshot API examples in Node.js, Python, and PHP](https://www.screenshotengine.com/docs/code-examples): Copy server-side ScreenshotEngine examples for Node.js, Python, PHP, and cURL, with API key environment variables and binary file handling. - [Full-page, mobile, PDF, and video screenshot recipes](https://www.screenshotengine.com/docs/capture-recipes): Practical ScreenshotEngine requests for full-page and mobile screenshots, CSS elements, dark mode, cookie banners, PDF, WebM video, and watermarks. - [Screenshot caching and fresh captures](https://www.screenshotengine.com/docs/caching): Understand ScreenshotEngine cache behavior, X-Cache response headers, successful-request usage, and the POST no-cache option for fresh screenshots. - [Screenshot API errors, rate limits, and troubleshooting](https://www.screenshotengine.com/docs/errors-and-limits): Resolve ScreenshotEngine HTTP 400, 401, 429, 500, and 503 errors. Understand monthly quotas, retry behavior, blank captures, and output files. - [Interactive explorer](https://www.screenshotengine.com/docs/explorer) - [OpenAPI specification](https://www.screenshotengine.com/openapi.json) - [Full documentation](https://www.screenshotengine.com/llms-full.txt) --- # Screenshot API quickstart Make your first ScreenshotEngine API request with cURL. Get an API key, capture a full-page PNG, and save the binary response. Source: https://www.screenshotengine.com/docs/quickstart ## 1. Get your API key Sign in to ScreenshotEngine, open the dashboard, and create an API key. Keep the key on your server in an environment variable. The examples below use a macOS or Linux shell; replace the placeholder with your own key. ```bash export SCREENSHOTENGINE_API_KEY="YOUR_API_KEY" ``` ## 2. Capture your first screenshot Send a POST request to https://api.screenshotengine.com/v1/screenshot with your key in the Authorization header and the target URL in a JSON body. This request captures the full page as a PNG and saves it as screenshot.png. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "format": "png", "height": "full" }' \ --output screenshot.png ``` ## 3. Open the returned file A successful request returns HTTP 200 and the file bytes directly. Open screenshot.png from your current directory. There is no job ID, polling step, or download URL to extract from JSON. Check the HTTP status before using a response as an image. Errors return JSON instead of file bytes. The cURL examples use --fail-with-body (cURL 7.76+) so an HTTP error also produces a nonzero exit status; the output file can still contain the error body. ## Use GET for simple requests GET uses query parameters, including api_key. Use --data-urlencode to preserve URLs containing query strings, spaces, or special characters. Prefer POST in server integrations to keep your API key out of the request URL. ```bash curl --fail-with-body --get 'https://api.screenshotengine.com/v1/screenshot' \ --data-urlencode "api_key=$SCREENSHOTENGINE_API_KEY" \ --data-urlencode 'url=https://example.com' \ --data-urlencode 'format=png' \ --data-urlencode 'height=full' \ --output screenshot.png ``` ## What happens if I only send a URL? The default output is a JPEG image at a 1280 × 720 viewport. Full-page capture, cookie banner removal, and dark mode are opt-in. Add height: "full", blockBanners: true, or darkMode: true to a POST body to enable them. --- # API keys and authentication Authenticate ScreenshotEngine GET and POST requests, store API keys securely, and understand the difference between query and Bearer authentication. Source: https://www.screenshotengine.com/docs/authentication ## Create and manage API keys Create an API key in your ScreenshotEngine dashboard. Save it in an environment variable such as SCREENSHOTENGINE_API_KEY or your deployment platform’s secret storage. Use a real account key for your integration. ## POST: Authorization header For POST /v1/screenshot, send Authorization: Bearer YOUR_API_KEY and Content-Type: application/json. Put capture options in the JSON body. An api_key field in that body does not authenticate the request. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "format": "png" }' \ --output screenshot.png ``` ## GET: api_key query parameter For GET /v1/screenshot, include api_key in the query string. The GET request schema requires it, so a Bearer header alone is not a substitute. Do not publish URLs containing your key in public HTML, repositories, or client-side JavaScript. ```text https://api.screenshotengine.com/v1/screenshot?url=https%3A%2F%2Fexample.com&api_key=YOUR_API_KEY ``` ## Integrating with a browser application Call ScreenshotEngine from your backend and return the resulting file to your frontend. A key embedded in a React component, a public environment variable, or an image URL can be read by visitors. If a key is exposed, create a replacement in the dashboard, update your server configuration, and revoke the old key. Avoid logging Authorization headers or query strings containing api_key. ## Can I capture a page behind a login? The documented screenshot endpoint accepts a public URL. It does not expose options for custom cookies, target-site Authorization headers, or login scripts. Your ScreenshotEngine API key authenticates the API call; it does not sign in to the website being captured. --- # Screenshot API parameter reference Compare GET and POST options for screenshots, PDF, WebM video, viewport sizes, CSS selectors, delays, watermarking, and cache control. Source: https://www.screenshotengine.com/docs/parameters ## Endpoint and request methods Use GET or POST at https://api.screenshotengine.com/v1/screenshot. GET accepts query strings. POST accepts a JSON body with Content-Type: application/json and a Bearer API key. Parameter names are case-sensitive. GET uses snake_case for options such as block_banners; POST uses camelCase such as blockBanners. Send actual booleans and numbers in JSON. ## Capture options Only url is required in the POST body. GET also requires api_key. The table lists the default behavior when an option is omitted. | POST field | GET parameter | Values and behavior | | --- | --- | --- | | url | url | Required. An absolute, publicly reachable HTTP or HTTPS URL. | | output | output | image (default), pdf, or scrolling_video. | | format | format | jpeg (default), png, or webp. Controls image output only. | | width | width | 1280 by default. GET validates 100–3840 pixels; use this range for POST too. | | height | height | 720 by default. A viewport height or "full" for full-page capture. GET validates numeric heights of 100–10000 pixels. | | blockBanners | block_banners | false by default. Set true to attempt cookie banner and consent-dialog removal. | | darkMode | dark_mode | false by default. Set true to request the target website’s dark color scheme. | | viewportDevice | viewport_device | Optional preset name from the list below. Overrides viewport width and height. | | selector | selector | Optional CSS selector, at most 200 characters. Captures the first matching element for an image. | | waitFor | wait_for | Optional delay after page load, in milliseconds. Use 0–30000. GET rejects values outside this range; the engine skips out-of-range POST delays. | | cachePolicy | Not available | default or no-cache. POST only. no-cache bypasses cache reads and writes. | | watermark | Not available | POST-only object for image watermarks. See fields below. | | pdfSettings.paperSize | pdf_paper_size | A4 (default), Letter, Legal, Tabloid, A3, or A5. Only for output=pdf. | | pdfSettings.orientation | pdf_orientation | portrait (default) or landscape. Only for output=pdf. | ## Available viewport presets Presets set the browser viewport dimensions. They do not emulate a physical device’s browser, touch input, user agent, or pixel density. To capture a full page at a specific mobile width, send width and height: "full" without a preset. | Preset | Width × height (CSS pixels) | | --- | --- | | desktop-1080p | 1920 × 1080 | | desktop-720p | 1280 × 720 | | desktop-4k | 3840 × 2160 | | macbook-pro-16 | 1728 × 1117 | | macbook-pro-14 | 1512 × 982 | | macbook-air-13 | 1470 × 956 | | iphone-15-pro-max | 430 × 932 | | iphone-15-pro | 393 × 852 | | iphone-15 | 393 × 852 | | iphone-14 | 390 × 844 | | iphone-se | 375 × 667 | | ipad-pro-12.9 | 1024 × 1366 | | ipad-pro-11 | 834 × 1194 | | ipad-air | 820 × 1180 | | ipad-mini | 768 × 1024 | | pixel-8-pro | 448 × 998 | | pixel-8 | 412 × 915 | | samsung-galaxy-s24 | 360 × 780 | | samsung-galaxy-s24-ultra | 412 × 915 | | samsung-galaxy-tab-s9 | 800 × 1280 | ## Watermark object Use watermark with image output. Do not combine it with PDF or scrolling video. Set text to a string of 1–100 characters. | Field | Default | Accepted values | | --- | --- | --- | | text | Required | 1–100 characters | | position | bottom-right | top-left, top-middle, top-right, middle-left, center, middle-right, bottom-left, bottom-center, bottom-right | | textColor | White | White, Black, Red, Blue (case-sensitive) | | backgroundColor | Black | White, Black, Red, Blue (case-sensitive) | ## Response content types Successful requests return HTTP 200 and raw file bytes. Read Content-Type to identify the result; do not call response.json() on a successful capture. | Output | Content-Type | Extension | | --- | --- | --- | | JPEG image | image/jpeg | .jpg | | PNG image | image/png | .png | | WebP image | image/webp | .webp | | PDF document | application/pdf | .pdf | | Scrolling video | video/webm | .webm | --- # Screenshot API examples in Node.js, Python, and PHP Copy server-side ScreenshotEngine examples for Node.js, Python, PHP, and cURL, with API key environment variables and binary file handling. Source: https://www.screenshotengine.com/docs/code-examples ## Before you run the examples Create an API key in the dashboard and set the SCREENSHOTENGINE_API_KEY environment variable. Run these examples on your server or local development machine. Each example checks the response status and writes a PNG file on success. ```bash export SCREENSHOTENGINE_API_KEY="YOUR_API_KEY" ``` ## Node.js: fetch and save a screenshot Use Node.js 20 or later with its built-in fetch. Save this example as screenshot.mjs and run node screenshot.mjs. It needs no additional packages. The 120-second client timeout is an example budget, not an API response-time guarantee. ```javascript import { writeFile } from "node:fs/promises"; const apiKey = process.env.SCREENSHOTENGINE_API_KEY; if (!apiKey) throw new Error("Set SCREENSHOTENGINE_API_KEY first"); const response = await fetch("https://api.screenshotengine.com/v1/screenshot", { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ url: "https://example.com", format: "png", height: "full", }), signal: AbortSignal.timeout(120_000), }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${await response.text()}`); } await writeFile("screenshot.png", Buffer.from(await response.arrayBuffer())); console.log("Saved screenshot.png"); ``` ## Python: download a screenshot This Python 3 example uses only the standard library. Save it as screenshot.py and run python3 screenshot.py. HTTP errors are reported before any image file is written. ```python import json import os from pathlib import Path from urllib.error import HTTPError from urllib.request import Request, urlopen payload = {"url": "https://example.com", "format": "png", "height": "full"} request = Request( "https://api.screenshotengine.com/v1/screenshot", data=json.dumps(payload).encode("utf-8"), headers={ "Authorization": f"Bearer {os.environ['SCREENSHOTENGINE_API_KEY']}", "Content-Type": "application/json", }, method="POST", ) try: with urlopen(request, timeout=120) as response: Path("screenshot.png").write_bytes(response.read()) except HTTPError as error: raise RuntimeError( f"HTTP {error.code}: {error.read().decode('utf-8', errors='replace')}" ) from error print("Saved screenshot.png") ``` ## PHP: capture with cURL Use PHP 8+ with the cURL extension enabled. Save this as screenshot.php and run php screenshot.php. JSON_THROW_ON_ERROR prevents silently sending invalid JSON. ```php true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 120, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $apiKey, 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'url' => 'https://example.com', 'format' => 'png', 'height' => 'full', ], JSON_THROW_ON_ERROR), ]); $body = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); $error = curl_error($curl); curl_close($curl); if ($body === false) { throw new RuntimeException($error); } if ($status < 200 || $status >= 300) { throw new RuntimeException("HTTP $status: $body"); } if (file_put_contents('screenshot.png', $body) === false) { throw new RuntimeException('Could not write screenshot.png'); } echo "Saved screenshot.png\n"; ``` ## cURL: a request from your terminal Use --output to save binary bytes to a file. The --fail-with-body option returns an error exit code for HTTP failures while keeping the response body available for debugging. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "format": "png", "height": "full" }' \ --output screenshot.png ``` --- # Full-page, mobile, PDF, and video screenshot recipes Practical ScreenshotEngine requests for full-page and mobile screenshots, CSS elements, dark mode, cookie banners, PDF, WebM video, and watermarks. Source: https://www.screenshotengine.com/docs/capture-recipes ## Capture a full-page screenshot Set height to "full" to capture beyond the initial viewport. The engine scrolls the page before capture to trigger scroll-based content. Sites with infinite scrolling or content loaded after long delays may need additional handling. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "format": "png", "height": "full" }' \ --output screenshot.png ``` ## Capture a mobile viewport Set viewportDevice to a supported preset, such as iphone-15-pro. This sets the viewport to 393 × 852 CSS pixels. It does not switch to Safari or simulate a physical iPhone. For a full-page mobile image, use width: 393 and height: "full" without viewportDevice. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "format": "png", "viewportDevice": "iphone-15-pro" }' \ --output mobile.png ``` ## Capture a specific element Set selector to a CSS selector. ScreenshotEngine waits for the first matching element to be attached and scrolls it into view. Use a selector that exists on the target page, such as h1 on example.com. An absent or non-visible element can cause the capture to fail. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "format": "png", "selector": "h1", "waitFor": 1000 }' \ --output element.png ``` ## Request dark mode and remove cookie banners darkMode asks the website to use its dark color scheme; the website must support that preference. blockBanners attempts to dismiss or remove cookie consent UI. These options do not guarantee every site changes theme or removes every banner. waitFor adds a delay after page load. Use a small value for client-rendered content; increasing it also increases request duration. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "format": "png", "darkMode": true, "blockBanners": true, "waitFor": 1500 }' \ --output dark.png ``` ## Convert a webpage URL to PDF Set output to pdf and use pdfSettings for paper size and orientation. PDF output uses the page’s print styling with background graphics enabled. It may look different from a screenshot. The endpoint takes a URL; it does not accept raw HTML. A4 portrait is the default. Omit watermark for PDF output. The format option only affects images. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "output": "pdf", "pdfSettings": { "paperSize": "A4", "orientation": "portrait" } }' \ --output page.pdf ``` ## Record a scrolling website video Set output to scrolling_video to return a WebM file. Use a numeric height for the video viewport. Save the response as .webm; format does not convert video to PNG, GIF, or MP4. Watermarks are not applied to video output. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "output": "scrolling_video", "width": 1280, "height": 720 }' \ --output website.webm ``` ## Add a text watermark to an image Send a watermark object in a POST body. Use one of the supported named colors, with the exact capitalization shown. The example places white text on a black background in the bottom-right corner. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "format": "png", "watermark": { "text": "Captured with ScreenshotEngine", "position": "bottom-right", "textColor": "White", "backgroundColor": "Black" } }' \ --output watermarked.png ``` --- # Screenshot caching and fresh captures Understand ScreenshotEngine cache behavior, X-Cache response headers, successful-request usage, and the POST no-cache option for fresh screenshots. Source: https://www.screenshotengine.com/docs/caching ## How screenshot caching works By default, production requests can reuse a capture with matching options from the API’s in-memory cache. Cache entries have a 24-hour lifetime, but can disappear earlier when an instance restarts. Cache availability can differ between instances; it is not persistent file storage. Changing capture options creates a different cache key. GET and POST requests are not guaranteed to share a cache entry. Save returned files in your own storage if you need permanent access. ## How do I force a fresh screenshot? Send a POST request with cachePolicy: "no-cache". This bypasses both cache lookup and cache storage, so it does not replace an existing cached screenshot. GET has no cachePolicy parameter. ```bash curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \ --header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "url": "https://example.com", "format": "png", "cachePolicy": "no-cache" }' \ --output fresh.png ``` ## Read the X-Cache response header Inspect response headers to see whether a capture was reused. In cURL, add --dump-header headers.txt to save headers separately from the binary body. | X-Cache | Meaning | | --- | --- | | HIT | The response was served from the capture cache. | | MISS | The response was generated without a cache hit. | | BYPASS | A POST request used cachePolicy: no-cache. | ## Do cached requests count toward usage? Successful screenshot requests count toward monthly usage, including cache hits. Failed requests do not count as successful captures. Request rate limits still apply. Cache your own returned files if you need to serve the same image repeatedly without new API calls. --- # Screenshot API errors, rate limits, and troubleshooting Resolve ScreenshotEngine HTTP 400, 401, 429, 500, and 503 errors. Understand monthly quotas, retry behavior, blank captures, and output files. Source: https://www.screenshotengine.com/docs/errors-and-limits ## Recognize an error response Successful captures return binary files. Errors return JSON, but the JSON shape depends on where the request failed. Check the HTTP status first, then inspect error, message, and any details fields. Do not assume every response has the same error properties. ```json { "error": "Quota Exceeded", "message": "You have reached your monthly screenshot limit." } ``` ## HTTP status codes and next steps Use the response body to distinguish a temporary rate limit from a monthly quota limit. Both can return HTTP 429. | Status | Likely cause | What to do | | --- | --- | --- | | 400 | Missing or invalid parameters, unsupported values, or URL security validation. | Check field names and types. Use a public HTTP(S) URL; localhost and private network targets are blocked. | | 401 | Invalid, missing, revoked, or origin-restricted API key. | Check your key and authentication method. POST uses a Bearer header; GET requires api_key. | | 429 · rate limit | Too many requests within the request window. | Honor Retry-After when present. Reduce concurrency and add a bounded retry delay. | | 429 · Quota Exceeded | Monthly screenshot allowance reached. | Check dashboard usage and your plan. Repeated immediate retries will not restore quota. | | 500 | Navigation, rendering, element capture, or internal failure. | Check the target URL and selector. Retry a small number of times for transient failures; contact support if it persists. | | 503 | The API is starting up or temporarily unavailable. | Wait a few seconds and retry with a capped backoff. | ## Request limits and monthly allowances Plans have a per-minute request limit and a monthly successful-capture allowance. The values below mirror the website’s plan configuration; check your dashboard for your account’s usage and billing details. Failed requests do not count toward the successful-capture allowance, but requests are still subject to rate limiting. | Plan | Screenshots / month | Requests / minute | | --- | --- | --- | | Free | 50 | 5 | | Starter | 3,000 | 40 | | Professional | 15,000 | 100 | | Engine | 60,000 | 250 | ## Choose a bounded retry strategy For temporary 429 or 503 responses, respect Retry-After when present. Otherwise start with a short delay, increase it on each retry, add jitter, and cap the number of attempts. For example, make at most three retries with increasing delays. Do not automatically retry invalid input, invalid credentials, or a monthly quota error. A client timeout can occur after a capture succeeds, so a retry can generate another successful request that counts toward usage. ## Common capture problems Blank or incomplete image: verify the target is publicly accessible, try a small waitFor delay, and use height: "full" for content below the fold. A site’s login screen or bot challenge is not bypassed by waiting longer. Dark mode has no effect: the target website must implement a dark theme that responds to the browser’s color-scheme preference. Unexpectedly old screenshot: use POST with cachePolicy: "no-cache". This bypasses the cache without updating old entries. Image viewer cannot open the file: inspect the HTTP status and Content-Type. You may have saved an error JSON body with a .png extension. An option has no effect: check GET versus POST field names. For example, send block_banners=true in a GET query, but blockBanners: true in a POST JSON body. Still stuck: contact support with the request method, target URL, non-secret options, HTTP status, and approximate request time. Remove API keys before sharing requests or logs.