ScreenshotAPI

Screenshot API

Complete reference for the GET /api/v1/screenshot endpoint — capture any web page as an image.

Endpoint

GET /api/v1/screenshot
POST /api/v1/screenshot

Captures a screenshot of the specified URL (or raw HTML via POST) and returns the binary image data directly in the response body. Requires API key authentication. Use POST when sending raw HTML via the html body parameter.

Authentication

Include your API key in one of these headers:

HeaderFormat
x-api-keysk_live_your_key_here
AuthorizationBearer sk_live_your_key_here

Query Parameters

Required

ParameterTypeDescription
urlstringThe URL of the page to screenshot. Must be a valid, fully-qualified URL (including https://).

Optional

ParameterTypeDefaultDescription
widthnumber1440Viewport width in pixels. Maximum: 1920.
heightnumber900Viewport height in pixels. Maximum: 10000.
fullPagestring"false"Set to "true" to capture the entire scrollable page. Ignores the height parameter when enabled.
typestring"png"Image format: "png", "jpeg", "webp", or "pdf".
qualitynumber100Image quality from 1 to 100. Only applies to JPEG and WebP formats. Ignored for PNG.
colorSchemestringForce color scheme: "light" or "dark". Emulates the prefers-color-scheme media feature.
waitUntilstring"networkidle2"Page load event to wait for before capturing. See Wait Strategies.
waitForSelectorstringCSS selector to wait for before capturing. The screenshot is taken once this element exists in the DOM.
delaynumber0Additional delay in milliseconds after the page loads and before the screenshot is taken. Range: 030000.
blockAdsbooleanfalseEnable ad blocking. Removes ads from the page before capture.
removeCookieBannersbooleanfalseAuto-remove cookie consent dialogs before capture.
cssInjectstringInject custom CSS into the page before capture. Useful for hiding elements or overriding styles.
jsInjectstringInject custom JavaScript into the page before capture. Runs after the page loads but before the screenshot is taken.
stealthModebooleanfalseEnable anti-bot-detection mode. Masks headless browser fingerprints to avoid being blocked by bot-detection systems.
devicePixelRationumber1Device pixel ratio for Retina/HiDPI captures. Accepted values: 1, 2, or 3. Higher values produce larger, sharper images.
timezonestringTimezone emulation (e.g. "America/New_York"). Overrides the browser's default timezone for the capture.
localestringLocale and Accept-Language emulation (e.g. "en-US"). Controls the language used by the browser during the capture.
cacheTtlnumber0Response cache TTL in seconds. When set to a value greater than 0, identical requests within the TTL window return a cached response. Set to 0 to disable caching.
preloadFontsbooleanfalsePreload all Google Fonts on the page before capture. Ensures accurate font rendering by explicitly loading every font discovered in the page's stylesheets.
removeElementsstringComma-separated CSS selectors for elements to remove before capture. Example: ".popup, #banner, .newsletter-signup". Each matching element is removed from the DOM.
removePopupsbooleanfalseAutomatically remove common popups, modals, overlays, and interstitials before capture. Targets elements with position: fixed/sticky and high z-index that match popup-like class names.
mockupDevicestringWrap the screenshot in a device frame. Values: "browser" (macOS chrome), "iphone" (iPhone with Dynamic Island), "macbook" (MacBook with bezel). Output is always PNG.
geoLatitudenumberLatitude for browser geolocation override. Must be used together with geoLongitude.
geoLongitudenumberLongitude for browser geolocation override. Must be used together with geoLatitude.
geoAccuracynumber100Accuracy in meters for the geolocation override. Only applies when geoLatitude and geoLongitude are set.

POST-only Body Parameters

ParameterTypeDescription
htmlstringRaw HTML string to render instead of navigating to a URL. When provided, the url parameter is ignored. Must use POST method with a JSON body.

Wait Strategies

The waitUntil parameter controls when the page is considered "loaded":

ValueDescription
loadWaits for the load event (all resources including images loaded).
domcontentloadedWaits for the DOMContentLoaded event (HTML parsed, but images/stylesheets may still be loading).
networkidle0Waits until there are no more than 0 network connections for 500ms. Best for fully static content.
networkidle2Waits until there are no more than 2 network connections for 500ms. Default. Good balance for most pages, tolerates long-polling or analytics connections.

For single-page applications (SPAs) that load content dynamically, combine waitUntil: "networkidle2" with waitForSelector targeting a key content element, or add a delay.

Response

Success (200)

Headers:

HeaderTypeDescription
Content-Typestringimage/png, image/jpeg, image/webp, or application/pdf
x-credits-remainingstringYour remaining credit balance
x-screenshot-idstringUnique identifier for this screenshot
x-duration-msstringTime taken to capture the screenshot in milliseconds

Body: Binary image data.

Error Responses

StatusBodyDescription
401{"error": "API key required"}No API key provided
402{"error": "Insufficient credits", "balance": 0}Not enough credits
403{"error": "Invalid API key"}API key is invalid or revoked

Examples

Basic Screenshot

curl "https://screenshotapi.to/api/v1/screenshot?url=https://example.com" \
  -H "x-api-key: sk_live_your_key_here" \
  --output screenshot.png
const response = await fetch(
  'https://screenshotapi.to/api/v1/screenshot?url=https://example.com',
  { headers: { 'x-api-key': 'sk_live_your_key_here' } }
)

if (!response.ok) {
  const error = await response.json()
  throw new Error(error.message)
}

const buffer = Buffer.from(await response.arrayBuffer())
await fs.promises.writeFile('screenshot.png', buffer)
import requests

response = requests.get(
    "https://screenshotapi.to/api/v1/screenshot",
    params={"url": "https://example.com"},
    headers={"x-api-key": "sk_live_your_key_here"}
)
response.raise_for_status()

with open("screenshot.png", "wb") as f:
    f.write(response.content)
req, _ := http.NewRequest("GET",
    "https://screenshotapi.to/api/v1/screenshot?url=https://example.com", nil)
req.Header.Set("x-api-key", "sk_live_your_key_here")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

file, _ := os.Create("screenshot.png")
defer file.Close()
io.Copy(file, resp.Body)
require "net/http"
require "uri"

uri = URI("https://screenshotapi.to/api/v1/screenshot?url=https://example.com")
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = "sk_live_your_key_here"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
  http.request(req)
}

File.binwrite("screenshot.png", response.body)
$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => "https://screenshotapi.to/api/v1/screenshot?url=https://example.com",
    CURLOPT_HTTPHEADER => ["x-api-key: sk_live_your_key_here"],
    CURLOPT_RETURNTRANSFER => true,
]);

$image = curl_exec($ch);
curl_close($ch);
file_put_contents("screenshot.png", $image);

Full-Page Screenshot

Capture the entire scrollable page as a single tall image:

curl "https://screenshotapi.to/api/v1/screenshot?url=https://example.com&fullPage=true&type=webp&quality=90" \
  -H "x-api-key: sk_live_your_key_here" \
  --output fullpage.webp
const params = new URLSearchParams({
  url: 'https://example.com',
  fullPage: 'true',
  type: 'webp',
  quality: '90'
})

const response = await fetch(
  `https://screenshotapi.to/api/v1/screenshot?${params}`,
  { headers: { 'x-api-key': 'sk_live_your_key_here' } }
)

const buffer = Buffer.from(await response.arrayBuffer())
await fs.promises.writeFile('fullpage.webp', buffer)
import requests

response = requests.get(
    "https://screenshotapi.to/api/v1/screenshot",
    params={
        "url": "https://example.com",
        "fullPage": "true",
        "type": "webp",
        "quality": "90"
    },
    headers={"x-api-key": "sk_live_your_key_here"}
)

with open("fullpage.webp", "wb") as f:
    f.write(response.content)
req, _ := http.NewRequest("GET",
    "https://screenshotapi.to/api/v1/screenshot?url=https://example.com&fullPage=true&type=webp&quality=90", nil)
req.Header.Set("x-api-key", "sk_live_your_key_here")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

file, _ := os.Create("fullpage.webp")
defer file.Close()
io.Copy(file, resp.Body)
require "net/http"
require "uri"

uri = URI("https://screenshotapi.to/api/v1/screenshot?url=https://example.com&fullPage=true&type=webp&quality=90")
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = "sk_live_your_key_here"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
  http.request(req)
}

File.binwrite("fullpage.webp", response.body)
$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => "https://screenshotapi.to/api/v1/screenshot?url=https://example.com&fullPage=true&type=webp&quality=90",
    CURLOPT_HTTPHEADER => ["x-api-key: sk_live_your_key_here"],
    CURLOPT_RETURNTRANSFER => true,
]);

$image = curl_exec($ch);
curl_close($ch);
file_put_contents("fullpage.webp", $image);

Dark Mode Screenshot

Force dark mode rendering on any page that supports prefers-color-scheme:

curl "https://screenshotapi.to/api/v1/screenshot?url=https://example.com&colorScheme=dark" \
  -H "x-api-key: sk_live_your_key_here" \
  --output dark.png

Custom Viewport Size

Capture at a mobile viewport size:

curl "https://screenshotapi.to/api/v1/screenshot?url=https://example.com&width=390&height=844" \
  -H "x-api-key: sk_live_your_key_here" \
  --output mobile.png

Wait for Dynamic Content

Wait for a specific element to appear before capturing:

curl "https://screenshotapi.to/api/v1/screenshot?url=https://example.com&waitForSelector=.hero-loaded&delay=500" \
  -H "x-api-key: sk_live_your_key_here" \
  --output dynamic.png

Rate Limits

There are currently no enforced rate limits. However, screenshots are generated sequentially per API key. For maximum throughput, use multiple API keys or send requests in parallel — each request will be queued and processed as resources become available.

Best Practices

  • Use networkidle2 (the default) for most pages. It handles analytics scripts and long-polling gracefully.
  • Use waitForSelector for SPAs where content loads asynchronously after the initial page load.
  • Use WebP format for smaller file sizes when quality is acceptable (typically 30–50% smaller than PNG).
  • Set appropriate viewport dimensions — the default 1440×900 works for most desktop pages, but use 390×844 for mobile screenshots.
  • Add a small delay (200–500ms) for pages with CSS animations or transitions that should complete before capture.

On this page