URL in, image out. One GET request, binary response,
no JSON envelope to unwrap — so the URL works directly inside an <img src>.
GET /take?url=https%3A%2F%2Fexample.com
They are a 200 with the wrong picture: a consent wall, a half-loaded page, a blank frame your pipeline records as a success. We built a 202-page benchmark of the real web to find them, and each of these is a fix it forced.
A one-shot sweep loses that race. We install an observer before any page script runs, so a banner that appears two seconds late is still removed.
Blocking the request does not reclaim the space. Most tools leave a grey gap that pushes content below the fold. We collapse the empty slot.
Waiting for an event modern sites never emit turns a 3-second capture into a timeout. We wait for interactive, then spend one bounded settle budget.
Some pages block their own main thread and stop answering. Every wait has a ceiling, so one stuck page cannot hold a slot or hang your request.
Detected with two independent signals and reported in a header. A bot wall is never silently returned as a success — or billed as one.
The headline use case is <img src>, where a raw key is a
billing incident waiting to happen. HMAC signed URLs are a v1 feature.
18 news front pages — consent walls, lazy images, heavy embeds — captured through all three APIs on the same day at the same viewport.
| 18 news pages | Screenshotline | ScreenshotOne | ApiFlash |
|---|---|---|---|
| Captured | 18/18 | 17/18 | 18/18 |
| timesofindia.com | 414 KB | 261 KB | 358 KB |
| Pages within 10% of the best | 13 of 17 | — | — |
Bytes are a proxy for how much of the page actually rendered. We publish the method rather than a marketing claim — and the one page we lose on is blocked at the network edge, not mis-rendered.
Same render — JavaScript executed, banners dismissed, lazy images loaded — read as text instead of photographed. Built for feeding live pages to models.
curl "https://api.screenshotline.com/extract?url=https%3A%2F%2Fexample.com&access_key=KEY"
app.netlify.com returns 121 characters of visible
text, and they read "The Netlify dashboard needs JavaScript :(".
Rendered first, the same URL returns the actual page. There is an
MCP server too, so agents can call it directly.
| url | Required. http or https. Private and reserved addresses are refused. |
| format | png (default), jpeg, webp, pdf |
| full_page | Capture the whole document. Scrolls first so lazy images load. |
| selector | Capture one element instead of the viewport. |
| viewport_width viewport_height | Defaults 1280×800. |
| device_scale_factor | 2 for retina output. |
| block_ads block_cookie_banners | Blocks the networks and sweeps leftover overlays. |
| delay | Extra wait in ms before capture, max 10000. |
| wait_until | domcontentloaded (default), load, networkidle0, networkidle2. The default is deliberate — see the docs. |
| cache cache_ttl | Serve from the store when warm. TTL in seconds. |
| access_key | Or the X-Access-Key header. |
| signature | HMAC of the sorted query. Required for browser-visible URLs. |
Full docs, with copy-paste quickstarts for curl, Node, Python, PHP and Go.