Taking a screenshot of a page is easy. Taking a screenshot of the entire page — every pixel, below the fold, past the lazy-loaded content — is where things get interesting.
Most headless browser setups require you to scroll the page, wait for images to load, calculate the full document height, resize the viewport, and then capture. That’s a lot of code for something that should be one parameter.
With len.sh, it is one parameter.
The Basics: full_page=true
curl "https://api.len.sh/v1/screenshot?url=https://example.com&full_page=true&access_key=YOUR_API_KEY" \
--output full-page.png
That captures the entire scrollable page from top to bottom in a single PNG. The default viewport width is 1280px, and the height extends to fit the full document.
Without full_page, you get only the visible viewport (1280x720 by default). With it, you get everything.
Handling Lazy-Loaded Content
Modern sites load images and content as you scroll. A naive full-page screenshot will capture placeholder elements instead of the actual content.
The wait_until parameter controls when len.sh considers the page ready:
| Value | Behavior |
|---|---|
load (default) | Wait for the load event |
domcontentloaded | DOM is parsed, don’t wait for images |
networkidle0 | No network activity for 500ms |
networkidle2 | At most 2 network connections for 500ms |
For pages with lazy loading, use networkidle2 to let content finish loading:
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com/blog\
&full_page=true\
&wait_until=networkidle2\
&access_key=YOUR_API_KEY" --output blog-full.png
If the page triggers loading via scroll events that a static viewport won’t fire, add a delay to give the browser extra time:
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com/feed\
&full_page=true\
&wait_until=networkidle2\
&delay=2000\
&access_key=YOUR_API_KEY" --output feed.png
Controlling Width and Format
Full page screenshots can get large. A few parameters help you control the output:
Width — set the viewport width to match your target device:
# Mobile-width full page
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com\
&full_page=true\
&width=390\
&access_key=YOUR_API_KEY" --output mobile-full.png
Format and quality — use WebP or JPEG to reduce file size:
# WebP at 70% quality
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com\
&full_page=true\
&format=webp\
&quality=70\
&access_key=YOUR_API_KEY" --output full-page.webp
Device emulation — capture as a specific device:
# Full page as iPhone 15
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com\
&full_page=true\
&device=iphone-15\
&access_key=YOUR_API_KEY" --output iphone-full.png
Available device presets include iphone-15, iphone-15-pro-max, ipad-pro, pixel-8, samsung-s24, macbook-pro-16, desktop-1080p, and desktop-4k.
Dealing with Fixed Headers and Sticky Elements
Fixed navigation bars and sticky elements can repeat across every “viewport” in a full page screenshot, creating visual noise. Inject custom CSS to hide them:
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com\
&full_page=true\
&css=header,nav,.sticky-bar,.fixed-banner{position:static!important;}\
&access_key=YOUR_API_KEY" --output clean-full-page.png
Or remove them entirely:
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com\
&full_page=true\
&css=.cookie-banner,.newsletter-popup{display:none!important;}\
&access_key=YOUR_API_KEY" --output no-popups.png
len.sh also has built-in blockers for common annoyances:
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com\
&full_page=true\
&block_ads=true\
&block_cookie_banners=true\
&block_popups=true\
&access_key=YOUR_API_KEY" --output clean.png
Capturing a Specific Element Instead
Sometimes you don’t want the full page. You want a specific section. The selector parameter captures just the matching element:
# Capture only the main content area
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com/article\
&selector=article.main-content\
&access_key=YOUR_API_KEY" --output article.png
This is useful for capturing specific components, charts, or content blocks without the surrounding page chrome.
Code Examples
JavaScript (Node.js)
const response = await fetch(
"https://api.len.sh/v1/screenshot?" +
new URLSearchParams({
url: "https://example.com",
full_page: "true",
wait_until: "networkidle2",
format: "webp",
quality: "80",
access_key: "YOUR_API_KEY",
})
);
const buffer = await response.arrayBuffer();
await Bun.write("full-page.webp", buffer);
Python
import requests
response = requests.get("https://api.len.sh/v1/screenshot", params={
"url": "https://example.com",
"full_page": "true",
"wait_until": "networkidle2",
"format": "webp",
"quality": 80,
"access_key": "YOUR_API_KEY",
})
with open("full-page.webp", "wb") as f:
f.write(response.content)
Using the len.sh SDK
import { LenSh } from "@len-sh/sdk";
const client = new LenSh({ accessKey: "YOUR_API_KEY" });
const screenshot = await client.screenshot({
url: "https://example.com",
fullPage: true,
waitUntil: "networkidle2",
format: "webp",
quality: 80,
});
await Bun.write("full-page.webp", screenshot);
Retina / High-DPI Screenshots
For crisp screenshots on retina displays, use the device_scale parameter:
# 2x retina full page screenshot
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com\
&full_page=true\
&device_scale=2\
&access_key=YOUR_API_KEY" --output retina-full.png
The output image will be 2560px wide (1280 viewport x 2 scale). File sizes increase proportionally, so consider using WebP format for retina captures.
Caching
Full page screenshots are cached by default for 24 hours (86400 seconds). Override this with cache_ttl:
# Cache for 1 hour
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com\
&full_page=true\
&cache_ttl=3600\
&access_key=YOUR_API_KEY" --output cached.png
# No cache (always fresh)
curl "https://api.len.sh/v1/screenshot\
?url=https://example.com\
&full_page=true\
&cache_ttl=0\
&access_key=YOUR_API_KEY" --output fresh.png
Cached screenshots are served from Cloudflare’s edge network, so subsequent requests for the same URL and parameters are fast.
Common Use Cases
Archiving — capture full page snapshots of web pages for legal or compliance records.
QA and testing — generate full page screenshots across multiple viewport widths to verify responsive layouts.
Portfolio and case studies — show complete page designs in client presentations.
Content monitoring — track visual changes to competitor pages, pricing pages, or product listings.
Documentation — capture tool interfaces and dashboards for user guides.
Pricing
Full page screenshots count as one screenshot toward your monthly quota, regardless of page length. The Free tier includes 100 screenshots/month. Pro (25,000/month) starts at EUR 19/month.
All plans include full API access with no feature gating.