Screenshot a web page
Capture any public web page as a PNG or JPEG, either the visible area or the whole scrollable page. An image is never a simple page, so a screenshot starts at the second tier rather than the first — everything above that is costed the same as a fetch. A page is always served the cheapest way that works, and costs more only when an easier attempt has genuinely failed — so an easy page never subsidises a hard one. `pagesFetched` and `usage.billableUnits` report what this particular request actually cost, in units, at three units to the credit: **1 for a simple page, 3 for a harder one, 6 for a hard one, 9 for the hardest**. The whole request runs inside a 120-second budget. Work that cannot finish in what is left of that budget is **skipped and reported as skipped**, never started and cut off halfway — which would bill for work that produced nothing. A 404 returns immediately: the page is not there, and working harder cannot change that. A 503 means the page could not be read at all, and it is not billed. The hardest pages are also the slowest. In a large burst some will exhaust the 120-second budget and come back unread rather than wrong, so expect a slow tail and retry it rather than sizing every timeout for the worst case. The image comes back base64-encoded in `imageBase64`, with its format, byte size and captured dimensions alongside. jpeg is much smaller than png on a photographic page. Billing: a screenshot starts at 3 units — one credit — rising to 6 on a hard page and 9 on the hardest. The cost is on every response as `pagesFetched`, and explained in `usage.billing`. A 503 is not billed.
/screenshot Pages https://api.fetchlayer.dev/web-unblocker/screenshot Headers
Authorization string required Bearer token — your FetchLayer API key.
Parameters
url string required The page to fetch. Must be an http or https address.
render string optional Whether to run the page in a browser: auto, always, never. auto only runs one when a direct read is not enough. (default: auto)
maxEffort string optional Your ceiling on how hard this request may try, cheapest first: basic, standard, advanced, maximum. It sets a ceiling on cost rather than choosing a tier — the cheapest that works is always used regardless. Set it to plain when you would rather a page failed than cost more than the cheapest tier. (default: solve)
country string optional Two-letter country code to read the page from, when the page differs by country.
session string optional An arbitrary label. Requests sharing a label are read over the same connection where possible, so a multi-step flow looks like one visitor.
assets string optional How much of the page to load: minimal, standard, full. minimal is the document only; standard loads what is needed to render, without images or video; full loads everything. Lower settings are faster and cheaper. (default: standard)
waitUntil string optional When to consider the page ready: domcontentloaded, load, networkidle. Only applies when the page runs in a browser. (default: domcontentloaded)
waitForSelector string optional A CSS selector to wait for before reading the page. If it never appears the request is reported unsuccessful rather than returning a partial page.
waitMs integer optional Extra time to let the page settle, in milliseconds, up to 15000.
expectText string optional Text that must appear on the page. If it does not, the request is reported unsuccessful rather than handing back the wrong page — a block page instead of the article you asked for.
device string optional Read the page as a desktop or mobile visitor. (default: desktop)
headers object optional Request headers to send to the page, such as Accept-Language or Referer. Headers that could impersonate another caller are not forwarded, and any that are dropped are listed in notes.
maxRedirects integer optional Redirects to follow before giving up, up to 20. Every hop is re-validated against the same address rules as the first.
format string optional Envelope format: json or markdown. (default: json)
fullPage boolean optional Capture the whole scrollable page rather than just the visible area. (default: false)
imageFormat string optional png or jpeg. jpeg is much smaller for a photographic page. (default: png)
Response Fields
screenshot
Screenshot a web page
transport string The source. Always "web".
notes string[] Caveats you can act on: a page that carried no readable text, a body cut short at maxBytes, request headers that were not forwarded, or an escalation ceiling that was applied.
pagesFetched number What this request cost, in units — the same number as usage.billableUnits, under the field name billing reads. It is a cost, not a page count. A unit is a third of a credit, and the figure reflects how hard the page was to get: a simple page is 1 unit, a harder one 3 (one credit), a hard one 6, and the hardest 9 (three credits). A 503 is not billed.
url string The address that was requested.
finalUrl string The address the request ended at, after redirects.
status number The HTTP status the page answered with.
redirects object[] Redirects that were followed, in order.
title string The page title, when it has one.
imageBase64 string The image, base64-encoded.
imageFormat string png or jpeg.
imageBytes number Size of the image in bytes.
width number Captured width in pixels.
height number Captured height in pixels.
fullPage boolean Whether the whole scrollable page was captured.
usage object What the request cost, how long it took, and how much came back.
usage.bytesTransferred number Bytes transferred across every attempt. A lower bound when a browser was used, because some responses do not declare their length.
usage.totalMs number Wall-clock time for the whole request, every attempt included.
usage.step string The effort level that served the page — basic, standard, advanced or maximum, the same vocabulary as the maxEffort ceiling. This is what the charge is derived from, so a request that cost more than expected says which tier it landed in.
usage.billableUnits number What this request cost, in units, at three units to the credit. The same number as pagesFetched. Charged requests run on a per-account counter rather than a fraction taken off each response, so one response shows the units and the credit falls on every third one — it averages to a third of a credit per unit over any real volume.
Request
curl -X POST "https://api.fetchlayer.dev/web-unblocker/screenshot" \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/","imageFormat":"jpeg"}'Response
{
"transport": "web",
"notes": [
"This page was run in a browser and still returned no readable text."
],
"pagesFetched": 2,
"url": "https://example.com/",
"finalUrl": "https://example.com/",
"status": 200,
"redirects": [],
"title": "Example Domain",
"imageBase64": "/9j/4AAQSkZJRgABAQAAAQ…",
"imageFormat": "jpeg",
"imageBytes": 31462,
"width": 1280,
"height": 720,
"fullPage": false,
"usage": {
"step": "standard",
"bytesTransferred": 671,
"totalMs": 7483,
"billableUnits": 3
}
}