Skip to main content

Screenshot API

Full-page screenshots of any URL, one flat price

The page as a browser draws it — the whole page by default, sized and cleaned up the way you need, with a link you can drop straight into an <img>.

By · Last updated: September 2026

TL;DR

POST a URL to /screenshot and get the whole rendered page back as a PNG — top to bottom, lazy images loaded, up to 16,384 px tall. screenshot_options change the viewport, pixel density, format, element, dark mode, hidden elements and CSS; every option is included in the same 1 credit.

Free plan, no credit card. 1,000 credits a month.

Try it now — no signup

Free · no signup · 2 runs every 10 minutes

…or try one of these

Your result will appear here.

Enter a URL above, or pick one of the example pages.

The request

One POST, one bearer token

POST /screenshot
curl -X POST https://urlpipe.dev/screenshot \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/pricing", "sync": true, "screenshot_options": {"viewport_width":390,"device_scale_factor":2,"format":"webp"}, "page_options": {"block_cookie_banners":true}}'
Response (Base64 WebP, truncated)
UklGRlq4AABXRUJQVlA4WAoAAAAgAAAARQUAhAUA…

X-Result-Url: https://urlpipe.dev/…  (no key needed, valid 30 days)

Defaults

What a screenshot captures by default

With no options, you get a full-page PNG: the whole scrollable document, not just the fold. The page is scrolled through first so lazy-loaded images are in the picture. The viewport is 1350 × 797 — a desktop window — so two captures of the same page line up and can be compared. The height follows the page up to 16,384 px; a longer page is captured down to that.

The body of the response is the image, Base64-encoded. Decode it to a file, or put it in a data: URI. If you only want to show it, you don't have to touch the bytes at all — see the image URL below.

screenshot_options

Every screenshot option

All optional, all included in the price. Out-of-range values are refused before anything is spent.

OptionValuesWhat it does
full_pagetrue (default) / falseThe whole page, or the viewport only (a #fragment URL scrolls to its anchor)
full_page_max_height100–16,384 pxThe tallest the image may be
viewport_width320–1920, default 1350Window width — 390 gives a phone layout
viewport_height240–1080, default 797Decides the fold and anything sized to the screen
device_scale_factor1–32 renders a retina image, with the high-resolution assets
selectorCSS selectorCapture one element — a pricing table, a chart
formatpng (default), jpeg, webpWebP is usually far smaller for a long page
quality1–100, default 80JPEG and WebP only
omit_backgroundtrue / falseTransparent where the page sets no background (PNG, WebP)
dark_modetrue / falseRenders with prefers-color-scheme: dark
hide_selectorsup to 50 selectorsHide a chat widget or promo bar in the image
stylesup to 20,000 charactersYour own CSS, injected before capture

What the page waits for and what it loses happens in page_options: block_cookie_banners, block_ads, remove_selectors, wait_for_selector and delay. The difference from hide_selectors: page options remove elements from the page itself, so they are gone from the HTML and Markdown too; hidden selectors only change the image.

Image URL

Put the image straight into an <img>

Every screenshot response carries an X-Result-Url header: a signed link to the same image that needs no API key and stays valid for the 30 days the result is kept. Use it in a page you render, a digest email or a social card, with nothing to proxy. An async request gets the same link in its webhook payload as result_url.

Link, not bytes
const res = await fetch("https://urlpipe.dev/screenshot", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://example.com", sync: true }),
})

img.src = res.headers.get("X-Result-Url")

Use cases

What people build with it

  • Visual regression checks. The default viewport is fixed, so two captures of the same page line up pixel for pixel. Capture before and after a deploy with max_age: 0 and diff the images in your own pipeline.
  • Social cards and thumbnails. selector captures one element, styles injects CSS to tidy it, and viewport_width with full_page: false gives a fixed-size frame.
  • Evidence and archives. A full-page capture records what a page showed on a given day — a price, a claim, a policy. labels tie each capture to a case or client, and the result stays retrievable for 30 days.
  • Mobile and dark-mode reviews. viewport_width: 390 and device_scale_factor: 2 show the phone layout as a retina image; dark_mode shows the theme a site serves to users who prefer it.
  • Link previews. When a page has no og:image, a viewport capture is the preview — see the metadata API.

Pricing

A flat price, whatever the options

A screenshot costs 1 credit — full page or viewport, PNG or WebP, 1× or 3×, with or without dark mode, CSS and hidden elements. The expensive dimensions are capped rather than metered: 16,384 px of height, a 20 MB image, 10 seconds each of delay and wait_for_selector. A capture you already took is reused for free while it is fresher than max_age, and a failed one costs nothing.

/scrape

Screenshot, metadata and Markdown from one visit

Link previews, archives and content audits usually need more than the picture. /scrape takes a list of operations and reads them all off one page load, so the screenshot, the metadata and the Markdown describe the same render:

POST /scrape
{
  "url": "https://example.com/blog/launch",
  "operations": ["screenshot", "meta", "markdown"],
  "screenshot_options": { "format": "webp", "full_page": false },
  "page_options": { "block_cookie_banners": true }
}

Each operation is billed as usual. Four screenshot options change how the page itself loads — viewport_width, viewport_height, device_scale_factor and dark_mode — so a screenshot with any of them takes its own visit, and the HTML beside it stays the page as it normally renders.

Limits

What it does not do

  • Images only. PNG, JPEG or WebP. For the page as a PDF, the PDF API returns it from the same kind of request, for 1 credit.
  • No video or scrolling captures. One still image per request.
  • No delivery to your storage. The image comes back in the response, the webhook or the result URL; there is no S3 or bucket upload. Copy it where you need it.
  • No interaction before capture. It can wait for an element, but not click or fill a form. A page behind a login is captured signed in with an auth profile.
  • Public addresses only. Private and intranet addresses are refused.

Pricing

What it costs

CallCreditsFree (calls/mo)Starter (calls/mo)Pro (calls/mo)Scale (calls/mo)
/screenshot1 credit1,00020,00055,000175,000

Cache hits and failed requests cost nothing. Paid plans are never cut off: past the allowance, extra credits are $1.50 per 1,000 credits. See every plan.

FAQ

Frequently asked questions

Yes. With no options you get the whole scrollable page as a PNG, up to 16,384 px tall, with lazy-loaded images scrolled into view first. Set full_page to false for the viewport only.

Make your first request in five minutes.

Free plan, no card. Confirm your email and your API key is live — you'll be making real requests in minutes.