Screenshot API: how to capture pages reliably
Need a screenshot API? One synchronous HTTP call renders a URL and returns an image. Learn when to use Playwright, spot blocked captures and estimate cost.
- screenshot api
- playwright
- puppeteer
- chrome devtools protocol
- web scraping
On this page
- What is a screenshot API and what does it call underneath?
- How do you take a screenshot with a screenshot API call?
- How viewport sizing works
- How do you wait for lazy-loaded and SPA content before capturing?
- How do you tell a blocked or empty screenshot from a good one?
- Why does the same URL render differently by exit IP and country?
- How much does a screenshot API capture cost?
- Screenshot API or Playwright and Puppeteer: which do you need?
- Frequently asked questions
- Is there a free screenshot API?
- Are failed screenshots billed?
- Can I take mobile-sized screenshots?
- Do I need Playwright to use a screenshot API?
- How long are screenshots stored?
- Which screenshot API step should you take next?
- Sources
A screenshot API is one HTTP call that renders a URL in a real browser and returns an image. Use it for one-shot captures. For login or click flows, use Playwright or Puppeteer over CDP, and check the image as well as the HTTP status, because a block page is still a valid image.
You need page captures for a monitor, a weekly report or an agent tool, and you have two routes: call a hosted screenshot API, or run headless Chromium yourself. Both return an image. They differ in who fixes what breaks and what each image costs.
After reading, you can pick a route for your job, set waits that match how your page loads, spot a capture that shows a challenge page or a blank render, and estimate cost per capture.
Key Takeaways
- Per Wayfern’s pricing, a screenshot costs 5 credits per capture.
- Failed Web Data calls aren’t billed, and each response reports the exact credits charged, per the pricing docs.
- Wayfern has no phone-size emulation, no free tier and no trial, and runs Chromium only, per its API reference.
- Wayfern keeps stored screenshots for 7 days under its published limits, so download anything you need longer.
What is a screenshot API and what does it call underneath?
A screenshot API is an HTTP endpoint that loads a URL in a real browser and returns the rendered page as an image or PDF. You send the URL and options such as viewport and format. The service drives Chromium through the Chrome DevTools Protocol, typically Page.captureScreenshot, so you never run the browsers yourself.

The Chrome DevTools Protocol’s Page domain documents Page.captureScreenshot with format, clip and captureBeyondViewport parameters. Over a raw CDP socket, one capture is a single message:
{"id": 1, "method": "Page.captureScreenshot",
"params": {"format": "png", "captureBeyondViewport": true}} The Page domain definition says the reply carries the image as base64 text in a data field.
Playwright’s page.screenshot() adds fullPage, clip and animations, and Puppeteer’s page.screenshot() is the equivalent in its own API.
A hosted API takes over the browser operations: launching, upgrading and routing through proxies. The capture step stays the same, so the same options still apply.
Older designs queue a job and make you poll for the result. Wayfern’s call is one synchronous request, or a CDP session over wss://api.wayfern.com/ws?token=LINK_TOKEN when the page needs clicks first. The API reference lists both.
How do you take a screenshot with a screenshot API call?
You take a screenshot with one synchronous POST to the Web Data API screenshot endpoint, a sibling of https://api.wayfern.com/api/v1/scrape. The image comes back on the same connection, so there’s no job to poll.
- Export your token. Put a
wf_token in theWF_TOKENenvironment variable so it never lands in your code. - Send the request. This call sets
urlandproxy: "auto".
curl -X POST https://api.wayfern.com/api/v1/screenshot \
-H "Authorization: Bearer $WF_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "proxy": "auto"}' \
-o response.json - Read the response. Wayfern’s API reference shows a
creditsfield with what the call debited. Compare that figure with the rates on the pricing page, and open the image before you trust it. - Download before it expires. Per the same reference, screenshots are kept 7 days, and page captures are cached for 1 hour.
Field names and output formats change, so copy them from the Web Data endpoint reference rather than from this snippet.
How viewport sizing works
Wayfern sizes a capture by resizing the real browser window. The API reference says: “The real browser window is resized, nothing is emulated and no script runs in your pages, so layout, media queries, outerWidth/outerHeight and screen.* stay consistent.” A breakpoint fires because the window is that wide, not because a script overrode a value.
Phone sizes aren’t offered. The browser presents a desktop device, so if you need a 390-pixel mobile layout from device emulation, use a tool that lists it.
Try the screenshot endpoint from the API reference
How do you wait for lazy-loaded and SPA content before capturing?
A reliable wait ties the capture to a condition the page proves, not to a guess about time. Fixed delays, network idle and selector waits each fail in a different way.
Fixed delay. A 3-second sleep guesses at load time. It’s too short on a slow exit and wasted on a fast one, so some runs return half-rendered pages and the rest run slow.
Network idle. Playwright’s docs mark the networkidle load state “DISCOURAGED” and define it as no network connections for at least 500 ms. A single-page app can sit quiet after its HTML shell arrives, before its JavaScript fetches data, so idle fires before hydration.
A page that polls an API or fires analytics beacons may never go idle at all.
Selector wait. Playwright’s page.waitForSelector() returns when the element you name satisfies its state option. You wait for the thing you came to capture, so the result doesn’t depend on load time.
Lazy images and infinite scroll load on scroll position, not elapsed time, so waiting longer loads nothing. Scroll in steps, then wait for the last image or list item.
Here is the pattern in Playwright:
await page.goto(url);
await page.waitForSelector("#results li:nth-child(20)");
await page.screenshot({ path: "page.png", fullPage: true, animations: "disabled" }); Playwright’s docs say fullPage takes a screenshot of the full scrollable page instead of the visible viewport. Setting animations to "disabled" stops CSS animations, CSS transitions and Web Animations, so a half-finished transition stays out of the image.
The screenshot endpoint is a single call, so check which wait options the API reference lists. If a page needs a scroll loop or a selector wait the endpoint doesn’t offer, connect Playwright over CDP instead, as in our guide to anti-detect browser sessions.
How do you tell a blocked or empty screenshot from a good one?
A challenge page, a cookie wall and a blank white render all encode to a normal PNG.
A failed capture usually looks like one of these:
- A “verify you are human” or access-denied page in place of your target.
- A mostly white image where scripts never finished rendering.
- A login or consent wall covering the content.
Check each response before you store it:
- Read the response fields. On an error, branch on the error body documented in the API reference. Don’t invent codes or match on message text.
- Compare against a known-good capture. Save one good image per target. A blank render has a much smaller byte size than a populated page, and a changed pixel height often means a wall replaced the content.
- Check the page itself on the CDP route. When you drive Playwright over CDP, assert
page.title()and wait for a marker element that only the real page contains before you callscreenshot().
Retry with backoff: wait 2 seconds, then 4, then 8, add random jitter, and stop after 3 attempts. A tight loop burns through limits that apply per client IP.
Wayfern’s limits page lists a default API limit of 120 requests a minute per client IP, with scrape at 60 a minute. Retries from one machine spend that same budget.
Automatic retry on a residential exit doesn’t replace your content check. Detection can still trigger on either exit, so keep your own check even when the call succeeds.
Wayfern’s API reference says failed requests are not billed. A call that returns an image has done its work, so read the credits field instead of assuming a challenge-page capture was free. Current rates are on the pricing page.
Why does the same URL render differently by exit IP and country?
The same URL renders differently by exit because a site sees only the IP address a request arrives from, and it can use that address’s network type and location to decide what to send back. Language, consent banners, regional content, pricing and block decisions can all depend partly on it.
A datacenter exit sits in a hosting provider’s network. A residential exit sits in an internet service provider’s network, the kind home users connect through.
A site can treat the two differently, and it can treat two countries differently. We can’t say what a given site does, so capture from the exit you care about and compare the images.
Wayfern’s API reference says proxy: "auto" “starts on a datacenter exit and retries on residential when blocked”. You can also force datacenter or residential and set a country. We make no promise about how often a retry succeeds.
The exit also changes the cost. Wayfern’s pricing lists “residential bandwidth 320 credits per GB” and “datacenter egress free”. A capture that stays on the datacenter exit adds no bandwidth charge, while a retry on residential can raise the credits charged.
Every response reports the exact credits charged, so you can see which path a capture took. Forcing datacenter caps that cost but returns whatever the site served.
The Browser API gives finer control for anti-detect browser sessions over CDP. Residential exits take country, region, city and isp, plus a sticky session id that holds one IP.
Wayfern’s page says an unknown location “is refused with close code 4007 instead of falling back to the wrong place”. A silent fallback would hand you a valid image of the wrong page.
How much does a screenshot API capture cost?
A Wayfern screenshot capture costs 5 credits at the base rate, which is $0.0625 at the list rate of $0.0125 per credit, as Wayfern’s pricing page publishes.
Three things move that figure:
- Exit type and bandwidth. Datacenter egress is free. Residential bandwidth is 320 credits per GB, which is $4.00 per GB at list rate.
- Concurrency headroom. Plans differ in pages open at once: 20 on Developer, 100 on Business and 400 on Scale.
- Retries. A retry you send is a new call with its own
credits_charged.
Credit packs lower the per-credit rate. 5,000 credits for $55 is $0.011 per credit, so a base capture costs $0.055. 20,000 for $200 is $0.01 per credit, or $0.05 per capture.
Packs never expire and work without a plan. Calls stop at zero, and auto top-up is off by default.
For competitor numbers, read each vendor’s own pricing page. Rates and free tiers change, and a figure copied here would go stale.
Screenshot API or Playwright and Puppeteer: which do you need?
You need a screenshot API for public pages that need no interaction, and Playwright or Puppeteer when a page needs a sign-in or clicks before the capture.
| Screenshot API (one call) | Self-run Playwright or Puppeteer | Playwright over CDP to a hosted browser | |
|---|---|---|---|
| Login, click, then capture | No, one request per page | Yes | Yes |
| Who runs Chromium | Wayfern | You | Wayfern |
| Image comes from | One POST | page.screenshot() | page.screenshot() |
| Engines | Chromium only | Whatever you install | Chromium only |
| Cookies between runs | Nothing kept | Your code | Your code saves and restores them |
Example: login, then capture. Connect with chromium.connectOverCDP("wss://api.wayfern.com/ws?token=LINK_TOKEN"), open the sign-in page and submit the form. Wait for a dashboard selector, then call page.screenshot().
Wayfern’s API reference says cookies and storage stay live while the socket is open, so the dashboard renders as the signed-in user. Our authenticated scraping use case documents this pattern.
AI agents on the live web get the same capture as a tool. The capture_screenshot tool runs on the MCP server at https://api.wayfern.com/mcp, takes a Bearer wf_ token with the mcp scope, and reports credits_charged on every call, as the MCP docs describe.
The honest catch: Wayfern has four limits here. There’s no free tier. There’s no mobile emulation, Chromium is the only engine (no Firefox or WebKit), and there are no persistent profiles, so you save and restore cookies in your own code.
If you need a few captures of a simple page each month, check the free tiers on the ScreenshotOne, ScreenshotAPI.net and screenshotapi.to pricing pages first.
- One-shot API: public pages, reports and monitors with no interaction.
- Self-run Playwright or Puppeteer: Firefox or WebKit captures, or when you want to own the browser fleet.
- Playwright over CDP: sign-in, clicks or multi-step flows without running Chromium yourself.
Frequently asked questions
Is there a free screenshot API?
Some vendors offer one. For a simple, low-volume need, check the free tiers on those vendors’ own pricing pages before you pay.
Wayfern has no free tier. The cheapest self-serve options are the Developer plan or a credit pack, and a screenshot costs 5 credits at the published rate on the pricing page.
Are failed screenshots billed?
No. Wayfern’s API reference says failed requests are not billed, and each response states the credits it debited. Read that field instead of estimating cost from your call count; the response fields are listed in the same reference.
Can I take mobile-sized screenshots?
No. The browser presents a desktop device, so Wayfern offers no phone sizes and no mobile emulation, as its API reference states. If you need phone-layout captures, pick an emulation-based tool instead.
Do I need Playwright to use a screenshot API?
No. You don’t install a browser or a driver to get the image. Reach for Playwright only for multi-step flows, such as logging in or clicking through a dialog before the capture.
How long are screenshots stored?
Screenshots are kept for 7 days, per the limits page in the docs. Download any image you need beyond that window and store it in your own bucket.
Which screenshot API step should you take next?
Your next screenshot API step is one test capture, so you know your real unit cost before you write a loop.
Today: Read the screenshot reference in the Wayfern docs and send one capture. Note the credits charged on the response.
This week: Add two guards to your screenshot API client. Inspect each response for a blocked or empty capture, and replace any fixed delay with a selector wait for the element you came for.
This month: Multiply your expected captures by the per-screenshot rate on the pricing page, then pick the plan or credit pack that covers that volume. List any target that needs a login or a click before capture, and connect Playwright over CDP for those.
To test it now, create a wf_ token and run the first capture from the docs quickstart. Buy the smallest credit pack, send one request and read the credits charged. Use the screenshot endpoint for one-shot pages, or the CDP route when the page needs steps first.
Sources
Screenshot API — Website Screenshots in Seconds |… · Pricing docs | Wayfern · Pricing - Credits for Browsers & the Web Data API | Wayfern · API Reference - CDP, Web Data & Search | Wayfern · Limits | Wayfern · Chrome DevTools Protocol - Page domain · Playwright Page class documentation · Anti-Detect Browser Sessions over CDP | Wayfern. Every other source is linked where the article cites it.
See us more often in Google
One click marks Wayfern as a preferred source in Google, so our posts can show up more often in your Top Stories, AI Mode and AI Overviews.