One URL in, one screenshot out.
Turn any web page into a PNG, JPEG or PDF with a single HTTP request. No headless browser to run, no SDK to install.
Live capture, no signup. Shared public demo with a small daily quota.
- PNG & JPEG screenshots
- PDF generation
- Full-page capture
- Custom viewport
- CSS selectors
- Change monitoring + webhooks
- One endpoint
GET /screenshot?url=… - No infrastructureNo Chromium to install or patch
- Predictable limits
429+Retry-After, never a silent hang - Free tier200 screenshots/month, no card
Running a headless browser yourself is a side project you didn't ask for.
Taking one screenshot is easy. Keeping it working in production is not. That's the part this API takes off your plate.
Heavy dependencies
A browser binary, system libraries and fonts on every server or CI runner that needs a capture.
Timeouts and hangs
Slow or broken pages need timeouts, size caps and clean error handling — or they block your workers.
Glue code for every format
Full page, viewport sizes, a single element, PDF output — each one is more code to write and maintain.
Built for developers who need a screenshot, not a screenshot platform.
If your product, script or pipeline needs to see a web page, one HTTP request is all it takes.
SaaS products
Show thumbnails of your users' sites, dashboards or pages inside your own app.
Link previews & OG images
Generate preview images of any URL at the exact viewport size you need.
QA & visual checks
Capture pages in CI, or let a monitor compare captures and call your webhook when something changes.
PDF generation
Save any page as a PDF that looks like the real page — viewport-sized or the full content.
Automations
Any script, cron job or workflow tool that can send an HTTP request can capture a page.
Agencies & archiving
Keep a record of how a client's page looked at a point in time, or track competitor pages.
Looking for something more specific? See dedicated pages for URL to PDF, website monitoring and visual regression testing.
Everything a capture needs. Nothing you have to learn.
Every option is a query parameter on the same endpoint.
PNG or JPEG
format=png or jpeg, with quality 1–100 for JPEG.
PDF output
format=pdf renders the page as it looks on screen, not a print stylesheet.
Full-page capture
full_page=true captures the whole scrollable page, up to 30,000px tall.
Any viewport
width / height from 200 to 2560px — mobile, tablet or desktop.
Single element
selector captures just one element by CSS selector.
Change monitoring
POST /monitors captures a URL on a schedule, compares it and calls your webhook on change.
Copy, paste, get a file back.
The response body is the image or PDF itself. No job IDs, no polling.
curl -G \ "https://screenshot-api-production-ffd7.up.railway.app/screenshot" \ -H "x-api-key: YOUR_API_KEY" \ --data-urlencode "url=https://example.com" \ -d "full_page=true" \ -d "format=png" \ -o screenshot.png
import { writeFileSync } from "node:fs";
const params = new URLSearchParams({
url: "https://example.com",
full_page: "true",
format: "png",
});
const res = await fetch(
"https://screenshot-api-production-ffd7.up.railway.app/screenshot?" + params,
{ headers: { "x-api-key": process.env.SCREENSHOT_API_KEY } }
);
if (!res.ok) throw new Error(await res.text());
const file = Buffer.from(await res.arrayBuffer());
writeFileSync("screenshot.png", file);
import os, requests
res = requests.get(
"https://screenshot-api-production-ffd7.up.railway.app/screenshot",
params={"url": "https://example.com", "full_page": "true", "format": "png"},
headers={"x-api-key": os.environ["SCREENSHOT_API_KEY"]},
timeout=30,
)
res.raise_for_status()
open("screenshot.png", "wb").write(res.content)
urlRequired. Any public http/https page.formatpng(default),jpegorpdf.full_pagetruefor the whole scrollable page.widthheightViewport, 200–2560px. Default 1280×800.selectorCapture one element (PNG/JPEG).quality1–100, JPEG only.
Full reference, limits and error codes in the docs.
From zero to your first capture in three steps.
Call the endpoint
GET /screenshot?url=… with your key in the x-api-key header.
Get the file
The response is the PNG, JPEG or PDF. Save it, store it, show it.
Screenshot Happy vs. running it yourself
What you'd build around Puppeteer or Playwright, already done.
| DIY headless browser | Screenshot Happy | |
|---|---|---|
| Setup | Install a browser, its system libraries and fonts | One HTTP request with an API key |
| Maintenance | Browser updates, crashes, memory | Handled for you |
| Formats | Code for each: full page, viewport, element, PDF | Query parameters |
| Change alerts | Build a scheduler, image diff and webhook sender | POST /monitors |
| Cost to start | A server that runs a browser | Free tier, then from €9/month |
There are other good screenshot APIs — ScreenshotOne, Urlbox, ApiFlash and more. If you're happy with one, there's no reason to switch. This one is small, self-contained and has a real free tier: a good fit for prototypes and side projects, or if you want to try something different before committing.
Screenshots and change monitoring, one plan.
No separate products, no usage billing to track. Each plan gives you more of both. Cancel any time.
Free
€0/month
No card required
- 200 screenshots/month
- 3 monitored pages, checked every 6h
- PNG, JPEG and PDF
Starter
€9/month
Billed monthly via Stripe
- 2,000 screenshots/month
- 20 monitored pages, checked every 1h
- Webhook alerts on change
Growth
€29/month
Billed monthly via Stripe
- 10,000 screenshots/month
- 100 monitored pages, checked every 15–30 min
- Webhook alerts on change
Over your quota you get a clear 429, never a surprise charge. Need more than Growth? Contact us.
Questions, answered.
Is there really a free plan?
Yes. 200 screenshots a month and 3 monitored pages, no card required. Enter your email in the docs and you get a key immediately.
Which output formats are supported?
PNG (default), JPEG with adjustable quality, and PDF. PDF renders the page as it looks on screen; add full_page=true for one page sized to the whole content.
What are the rate limits?
10 requests per minute per API key, on every plan, plus your plan's monthly quota. Over a limit you get a 429 with a Retry-After header — never a silent hang.
What happens if I go over my monthly quota?
Requests return a clear 429 telling you so. There is no overage billing and no surprise charge. You can upgrade at any time.
How does change monitoring work?
One POST /monitors call with a URL, a webhook and a check interval. The page is captured on that schedule, compared with the previous capture, and your webhook is called when the difference crosses your threshold. It needs your own API key — the public demo can't create monitors.
Can I cancel or change plans?
Yes, no contracts. Manage or cancel your subscription yourself from the billing portal in the docs with your API key.
Is the demo on this page real?
Yes — it calls the same /screenshot endpoint with a shared public key that has a small daily quota for all visitors. For regular use, get your own free key.
Something isn't working. Who do I ask?
Use the support form in the docs and we'll reply by email.
Your first screenshot is one request away.
Try the live demo above, or get a free API key and call it from your own code.