Skip to content
Docs

Screenshot a page

Capture one public URL as it looks to a visitor and return the image.

POST/v1/screenshot
1–5 creditsTry itScreenshot API overview →1 for most pages, 5 for a site that refuses standard requests or with country, 75 with premium (5 or 75 held while it runs); a non-2xx page and failed requests are free

The quickest call is one GET with your key in the URL; the body is the image, saved as screenshot.webp:

One line
curl -f "https://api.scrapercompany.com/v1/screenshot?api_key=$SCRAPERCOMPANY_API_KEY&url=https%3A%2F%2Fexample.com&format=webp" -o screenshot.webp
The image the one-line call returned: the example.com page at the default 1440 by 900 viewport
A real answer, from the one-line call: example.com at the default 1440 x 900 viewport, WebP, 35 KB, 1 credit. Captured 27 October 2026.

The page runs its JavaScript and loads its images, styles and fonts, then is waited on until wait_until (load by default) and any wait_for selector or wait_ms, then captured: the viewport (width x height, 1440 x 900 by default, at scale 1-3), the whole page (full_page), or one element (selector). format is png, jpeg (or jpg) or webp, with quality for the last two. GET takes the same fields as query parameters (fullPage is read as full_page) and the key as api_key.

The default answer is the image itself, with the site's own status in X-Upstream-Status; response_type=json returns it base64-encoded with that status and metadata. A refused request is retried automatically; premium=true uses the premium network from the first attempt, country loads the page from that country, and session_id keeps one IP address.

1 credit for most pages; 5 for a site that refuses standard requests (the capture moves to the fallback network) and with country; 75 with premium. 5 (75) is held while the capture runs, so that much must be available; x-credits-charged says what was charged. Only a 2xx page that produced an image is charged: a non-2xx page is still returned, free. A site that refuses every attempt, a timeout_s that runs out, or a wait_for or selector that never appears is a free 503; private and internal addresses are refused (422).

Request

POSThttps://api.scrapercompany.com/v1/screenshot

Authenticate with your API key in the x-api-key header (see Authentication).

Run this request on your own API key from this page, with the values you type. Signed out? Sign in or get an API key.

Body

JSON object. Unknown fields are rejected with 422.

  • urlstringrequiredmin length 1, max length 2048

    The page to capture: an absolute http:// or https:// URL on port 80, 443, 8080 or 8443. Private, loopback and cloud-metadata addresses, and hosts on the scrape denylist, are refused (422), as is any redirect to one.

  • formatstringdefault png

    Image format: png (default, lossless), jpeg (jpg accepted) or webp.

    One ofpngjpegwebp

  • qualityinteger | nullmin 1, max 100

    JPEG or WebP quality, 1-100 (default 80). Not for png, which is lossless (422).

  • full_pagebooleandefault false

    Capture the whole scrollable page instead of the viewport. Not with selector.

  • widthintegerdefault 1440min 320, max 3840

    Viewport width in CSS pixels, 320-3840 (default 1440).

  • heightintegerdefault 900min 240, max 2160

    Viewport height in CSS pixels, 240-2160 (default 900). With full_page the image is as tall as the page.

  • scalenumberdefault 1min 1, max 3

    Device pixel ratio, 1-3: 2 gives a retina image twice the viewport's size in pixels.

  • wait_untilstringdefault load

    When the page counts as loaded: domcontentloaded (HTML parsed), load (default: images and styles in) or networkidle (no requests for 500 ms). load and networkidle are waited for as long as timeout_s allows; a page that never settles is captured as it stands.

    One ofdomcontentloadedloadnetworkidle

  • wait_forstring | nullmin length 1, max length 500

    CSS selector to wait for before the capture, e.g. #prices .row. Never appearing within timeout_s is a free 503: retry, or allow more time.

  • wait_msintegerdefault 0min 0, max 10000

    A further fixed wait, in milliseconds (0-10000), before the capture.

  • selectorstring | nullmin length 1, max length 500

    Capture only the first element matching this CSS selector (waited for until it is visible), e.g. #chart.

  • premiumbooleandefault false

    Use the premium network from the first attempt, for sites that block standard requests. 75 credits instead of 1-5.

  • countrystring | null

    Two-letter country (ISO 3166-1) the page must be loaded from, e.g. DE, for local prices, language and consent banners. 5 credits.

    251 allowed values

    AD, AE, AF, AG, AI, AL, AM, AO, AQ, AR, AS, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO, BQ, BR, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, FI, FJ, FK, FM, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP, GQ, GR, GS, GT, GU, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MH, MK, ML, MM, MN, MO, MP, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL, PM, PN, PR, PS, PT, PW, PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL, SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UK, UM, US, UY, UZ, VA, VC, VE, VG, VI, VN, VU, WF, WS, XK, YE, YT, ZA, ZM, ZW

  • timeout_sintegerdefault 45min 1, max 90

    Seconds the whole capture may take, every attempt included: at most 90 (default 45). Running out is a free 503 with Retry-After.

  • session_idstring | nullpattern ^[A-Za-z0-9_-]{1,64}$

    Keep the same IP address across requests that share this id (letters, digits, _, -; up to 64); ids are scoped to your API key.

  • response_typestringdefault image

    image (default): the image itself, with the site's status in X-Upstream-Status. json: a JSON object with the image base64-encoded in image, plus the status and metadata.

    One ofimagejson

  • headersobject

    Headers to send to the target, e.g. Accept-Language or a Cookie you hold for the site. Hop-by-hop headers, Host, Content-Length, Proxy-* and anything named like an API-key header (X-API-Key) are dropped; Authorization and Cookie are not sent on to another host after a redirect. With render they go with the page request only. At most 32.

Example request

curl -f -X POST "https://api.scrapercompany.com/v1/screenshot" \
  -H "x-api-key: $SCRAPERCOMPANY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com"
  }' \
  -o screenshot.png

Response

200 — The image (response_type image, the default) or JSON carrying it base64-encoded (response_type json); the image answer has the site's status in X-Upstream-Status and the final URL in X-Final-Url. Metered responses carry x-credits-charged and x-credits-remaining headers (see credit headers).

By default the body is the image itself (image/png, image/jpeg or image/webp, as format asks), with the site’s status in the X-Upstream-Status header and the final URL in X-Final-Url. An error is always JSON, never an image. With response_type: json the answer is JSON instead, carrying the same image base64-encoded:

200 response with response_type: json
{
  "url": "https://example.com/",
  "final_url": "https://example.com/",
  "status_code": 200,
  "format": "png",
  "media_type": "image/png",
  "image": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",
  "meta": {
    "render": true,
    "premium": false,
    "elapsed_s": 2.84,
    "format": "png",
    "width": 1440,
    "height": 900,
    "scale": 1,
    "full_page": false,
    "image_bytes": 21873
  }
}
The default answer is the image itself; this is the JSON form.

Errors

Errors return a JSON body with a detail field. Failed requests are not charged. See Errors for the full list and retry advice.

StatusMeaningRetry?
401Unauthorized

Missing or invalid API key.

{"detail":"missing or invalid API key"}
No, fix the request
402Payment Required

Not enough credits for this request: the account's credits mode is enforce (mode in GET /v1/billing) and the request costs more than the available credits. Nothing is run or charged.

{"detail":"insufficient credits: this request costs 5, 0 available. Credits renew 2026-11-01."}
No, fix the request
422Unprocessable Content

Request validation failed. detail is a list of problems for schema errors, or a string for semantic checks performed by the endpoint.

{"detail":[{"loc":["body","name"],"msg":"Field required","type":"missing"}]}
No, fix the request
429Too Many Requests

Too many requests: the key's requests-per-minute limit was exceeded, or (in enforce credits mode) the plan's concurrent-request limit. No rate-limit or Retry-After headers are sent; back off and retry.

{"detail":"rate limit 60/min exceeded"}
Yes, with backoff
503Service Unavailable

Temporarily unavailable: a dependency of this endpoint is down, or the upstream source changed its contract. Retry later.

{"detail":"database unavailable: OperationalError"}
Yes, with backoff

Try it

Press Try it above to run this request on your own key, with the values you type (sign in first). For a no-code walkthrough, use the workspace’s guided Try it.

  1. Export your key: export SCRAPERCOMPANY_API_KEY=sk_... (no key yet? start a free trial).
  2. Copy the cURL example above and run it in a terminal.

Credits

From 1 credit per successful call (1 for most pages, 5 for a site that refuses standard requests or with country, 75 with premium (5 or 75 held while it runs); a non-2xx page and failed requests are free). Failed, blocked and empty results are free.

Questions about this page?

Send the page link and your question, and the team will answer.

Email support