Use cases
A picture of every page, top to bottom
Full-page captures on a schedule — small enough to keep, consistent enough to compare.
By Roger Campos · Last updated: September 2026
TL;DR
To archive web pages visually, capture each one full-page on a schedule, in a compact format, and store the image with the date and URL. URLpipe's /screenshot captures the whole scrollable page — up to 16,384 pixels tall — as PNG, JPEG or WebP, in light or dark mode, for 1 credit whatever the options.
Free plan, no credit card. 1,000 credits a month.
The job
Why archive screenshots at all
Design teams keep a history of their own site. Marketing keeps competitors' landing pages. Compliance keeps what a disclosure page said on a given date. A text archive loses the layout; a screenshot keeps what a visitor actually saw.
/screenshot is built for this shape of job. It scrolls through the page first so lazy-loaded images are in the picture, captures the whole document rather than the fold, and uses the same default 1350 × 797 viewport every time, so two captures of a page line up.
Settings
The options that make an archive
format: "webp"withquality— WebP is usually the smallest by far for a long page, which is what decides the storage bill of an archive.dark_mode: true— a second capture withprefers-color-scheme: dark, for sites with a dark theme.viewport_width: 390— the phone layout, when you archive responsive designs.full_page_max_height— the ceiling is 16,384 px; set it lower to cap infinite-scroll pages.page_options.block_cookie_bannersandblock_ads— take the consent wall and ad slots out of the page before it is drawn. Nothing is clicked, so no consent is given on anyone's behalf.
Every option is included in the 1-credit price. Pair each capture with /html if you want the rendered DOM as well — the text stays searchable after the picture is filed away.
Flow
A weekly capture, end to end
- 1A weekly job sends one request per page and theme, async, labelled with the page id and theme.
- 2The webhook delivers the image as Base64 in
result. Decode it and write it to your storage underpage/date/theme.webp. - 3Store the file yourself: results are kept for 30 days, and
result_urlexpires with them. An archive is the copy you keep, not the link. - 4Diff this week's image against last week's if you want an alert when a page's look changes.
import base64, os, requests
from datetime import date
API = "https://urlpipe.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['URLPIPE_API_KEY']}"}
def capture(page_id: str, url: str, dark: bool = False) -> None:
res = requests.post(f"{API}/screenshot", headers=HEADERS, json={
"url": url,
"sync": True,
"screenshot_options": {"format": "webp", "quality": 80, "dark_mode": dark},
"page_options": {"block_cookie_banners": True, "block_ads": True},
"labels": {"page": page_id, "theme": "dark" if dark else "light"},
}, timeout=75)
res.raise_for_status()
path = f"archive/{page_id}/{date.today()}/{'dark' if dark else 'light'}.webp"
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "wb") as f:
f.write(base64.b64decode(res.text))import { mkdir, writeFile } from "node:fs/promises";
export async function capture(pageId, url, dark = false) {
const res = await fetch("https://urlpipe.dev/screenshot", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.URLPIPE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url,
sync: true,
screenshot_options: { format: "webp", quality: 80, dark_mode: dark },
page_options: { block_cookie_banners: true, block_ads: true },
labels: { page: pageId, theme: dark ? "dark" : "light" },
}),
});
if (!res.ok) throw new Error(`URLpipe ${res.status}`);
const dir = `archive/${pageId}/${new Date().toISOString().slice(0, 10)}`;
await mkdir(dir, { recursive: true });
await writeFile(`${dir}/${dark ? "dark" : "light"}.webp`,
Buffer.from(await res.text(), "base64"));
}curl -s -X POST https://urlpipe.dev/screenshot \
-H "Authorization: Bearer $URLPIPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/pricing",
"sync": true,
"screenshot_options": {"format": "webp", "quality": 80, "dark_mode": true},
"page_options": {"block_cookie_banners": true}
}' \
| base64 --decode > pricing-dark.webpThe sync version above is the easiest to read. For hundreds of pages, send them async with report_to and keep no more in flight than your plan's parallel limit — a queued async request counts toward it.
Consistency
Captures you can compare
An archive is most useful when this week's image can be laid over last week's. Three things keep captures comparable:
- A fixed viewport. The default 1350 × 797 is the same on every request; if you set your own, set it everywhere.
- Hide what moves.
hide_selectorstakes a chat widget, a live date or a rotating banner out of the image while leaving it in the HTML, up to 50 selectors. - Freeze animation.
stylesinjects your own CSS before the capture, up to 20,000 characters — enough to stop carousels and transitions mid-flight.
{
"url": "https://example.com/",
"screenshot_options": {
"format": "png",
"hide_selectors": ["#intercom-container", ".live-clock"],
"styles": "*, *::before, *::after { animation: none !important; transition: none !important; }"
},
"page_options": { "block_cookie_banners": true }
}Use PNG when you diff pixels — it is lossless, so an unchanged page gives identical bytes in the regions that didn't move. Keep WebP for the copies you only look at.
Credits
What it costs
A thousand pages captured weekly in both themes, with an HTML snapshot, at list price:
| What | A month | Credits each | Credits |
|---|---|---|---|
| Full-page WebP, light theme (weekly, 1,000 pages) | 4,000 | 1 | 4,000 |
| Full-page WebP, dark theme | 4,000 | 1 | 4,000 |
| Rendered HTML snapshot | 4,000 | 1 | 4,000 |
12,000 credits; the cheapest plan that covers it is Starter: $19 a month for 20,000 credits. A capture exactly a week after the last can still land inside the default seven-day max_age, so send max_age: "6 days" — or 0 — to be sure each week's capture is a fresh one rather than last week's stored image.
Limits
What URLpipe does not do for archiving
- Keep your archive. Results are retained for 30 days. Long-term storage is yours.
- Record WARC files or replay. You get an image and, if you ask, the rendered HTML — not a replayable web archive with every resource.
- Certify. A screenshot with a date is a record, not notarised evidence. If you need legal-grade proof, use a service built for it.
- Capture pages taller than 16,384 px in one image. Longer pages are captured down to that height.
- Capture motion. Still images only; no video of the page loading.
Endpoints
The endpoints on this page
- Screenshot any website from its URL
Paste a link and get a full-page PNG of the rendered page — JavaScript executed, exactly as a real browser would draw it. Great for previews, monitoring and visual QA.
Try it free - Get the rendered HTML of any URL
Paste a link and get the page's HTML after JavaScript has run and redirects have been followed — the DOM a real browser sees, not the empty shell curl returns.
Try it free
FAQ
Frequently asked questions
Does it capture the full page or just the visible part?
Which format is best for archiving?
Can I capture the dark-mode version of a site?
How long are screenshots kept?
Build it on the free plan.
Free plan, no card. Confirm your email and your API key is live — you'll be making real requests in minutes.