Website Screenshot API in Python: Viewport or Full-Page PNG, Paid per Call
Take a screenshot of a public web page from Python and save it as a PNG. /v1/screenshot returns the 1280x800 viewport for $0.008 and /v1/screenshot/full the whole scrollable page for $0.012, JavaScript rendered, paid per call in USDC on Base over x402. No signup or API key, and you are charged only when an image comes back.
Payment note: An unpaid call returns HTTP 402 with the exact x402 terms: scheme exact, network Base (eip155:8453), USDC, amount 8000 for /v1/screenshot or 12000 for /v1/screenshot/full (USDC has 6 decimals, so $0.008 and $0.012). The x402 client signs a payment for exactly that amount and retries the call. Payment settles only when an image comes back.
Steps
- Install the x402 client. pip install "x402[requests,evm]" and export a Base wallet key holding a little USDC as AGENT_KEY. Use a dedicated wallet with a small balance.
- Read the price for free. Call the endpoint without paying. The 402 response carries the terms in the PAYMENT-REQUIRED header and the same terms as JSON in the body.
- Pay and capture. POST {"url": "https://..."} through the x402 session. It signs the payment and retries automatically.
- Decode and save. The JSON response has url, full_page, format ("png"), content_type, width, height, bytes, image_base64, ms and attempts. Base64-decode image_base64 and write it to a .png file.
- Handle the free failures. Not charged: 400 (URL not allowed: private or reserved address, credentials, non-default port), 502 (no image came back) and 503 (paused or at capacity).
Code
curl: read the price without paying (HTTP 402)
curl -s -i -G https://api.switch402.com/v1/screenshot -H 'User-Agent: my-agent/1.0' \
--data-urlencode 'url=https://example.com' \
| grep -i '^payment-required' | cut -d' ' -f2 | tr -d '\r' | base64 -d
# {"x402Version":2, ... "accepts":[{"scheme":"exact","network":"eip155:8453","amount":"8000", ...}]}
# /v1/screenshot/full answers the same way with "amount":"12000"Python: viewport screenshot (1280x800) saved as a PNG
# pip install "x402[requests,evm]"
import os
from eth_account import Account
from x402 import x402ClientSync
from x402.http.clients import x402_requests
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact import ExactEvmScheme
client = x402ClientSync()
client.register("eip155:8453", ExactEvmScheme(signer=EthAccountSigner(Account.from_key(os.environ["AGENT_KEY"]))))
session = x402_requests(client)
session.headers["User-Agent"] = "my-agent/1.0"
import base64
r = session.post("https://api.switch402.com/v1/screenshot", json={"url": "https://example.com"}) # $0.008
if r.status_code != 200:
raise SystemExit(f"HTTP {r.status_code}: no image, not charged")
shot = r.json()
with open("example.png", "wb") as f:
f.write(base64.b64decode(shot["image_base64"]))
print(shot["width"], "x", shot["height"], shot["bytes"], "bytes in", shot["ms"], "ms")Python: full-page screenshots for a list of URLs
# uses the x402 session from the example above
import base64, re
urls = ["https://example.com", "https://example.org"]
for url in urls:
r = session.post("https://api.switch402.com/v1/screenshot/full", json={"url": url}) # $0.012 each
if r.status_code != 200:
print(url, "skipped, HTTP", r.status_code, "(not charged)")
continue
shot = r.json()
name = re.sub(r"[^a-z0-9]+", "-", url.lower()).strip("-") + ".png"
with open(name, "wb") as f:
f.write(base64.b64decode(shot["image_base64"]))
print(name, shot["width"], "x", shot["height"])You pay only for the pages you actually fetch: $0.008 per standard page on /v1/scrape, $0.003 per lite call on /v1/scrape/lite, in USDC on Base and charged only on success. No subscription or unused credits; optional prepaid packs and a $10 monthly plan.
FAQ
- How much does a screenshot cost?
- $0.008 per viewport screenshot on /v1/screenshot and $0.012 per full-page screenshot on /v1/screenshot/full, in USDC on Base, confirmed from the live 402 terms and openapi.json on Oct 31, 2026. 100 viewport screenshots cost $0.80, and a month with no screenshots costs $0.
- Am I charged if the capture fails?
- No. Payment settles only when an image comes back. 400, 502 and 503 responses are not charged.
- Can I set the viewport size, device, delay or format?
- Not today. The only input is the URL. The viewport is fixed at 1280x800, the full-page route captures the whole scrollable page at 1280 px wide, and PNG is the only format.
- How big can the image be?
- Images are capped at 8 MB. The full-page route covers the whole scrollable page as long as the PNG stays within that cap.
- How long does a capture take?
- It depends on the page. Every response includes ms, the time the capture took, so you can measure it for your own URLs.
- Can it capture pages behind a login?
- No. Public http(s) pages on default ports only. Private or reserved addresses and URLs with credentials return 400 and are not charged.
- Do I need an account or API key?
- No. A wallet pays per call over x402. If you prefer a balance, optional prepaid packs and a $10 monthly plan are available; with a prepaid key, send Authorization: Bearer <key> and each successful call debits its own price.
Related
- API docs
- Use cases
- Pricing calculators
- All guides
- Full-page screenshot API ($0.012)
- Screenshot API without a subscription
- Scrape a website to markdown in Python
- Add web scraping to Claude Desktop (MCP)
- Add web scraping to Cursor (MCP)
- Pay per request with x402 and USDC
- Web search MCP in Claude Code
- Web scraping in n8n, pay per use
- LangChain web scraper tool
- CrewAI web scraping tool
- PDF text extraction in Python