The url parameter is the core input for every url to image API call. Pass a URL, get back an image. PNG by default. You can switch to JPEG, WebP, AVIF, or TIFF with one more parameter, and the API loads the page in a real Chromium instance, waits for content to render, and returns the result as a binary file or base64 string.
How URL to image conversion works
Every capture starts the same way. You send a GET request with the target URL, the API spins up an isolated Chromium browser context, navigates to the page, waits for content to settle, and takes a screenshot. The response is a binary image file.
curl "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://example.com\
&format=png\
&width=1280" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o screenshot.png
That's a complete request. One URL, one image. The browser context is destroyed after each capture, so cookies, localStorage, and session state don't leak between requests.
Response times depend on the target page. A static marketing site renders in 2-3 seconds. A JavaScript-heavy SPA with third-party widgets might take 6-8 seconds, though I've seen Next.js dashboards that need a full 12 before the charts populate. The API handles the waiting internally by monitoring network activity and DOM mutations to decide when the page is stable enough to capture.
Choosing the output format
Six formats, each one built for a different workflow:
| Format | Best for | File size | Notes |
|---|---|---|---|
png | Visual regression testing, compliance records | Largest | Lossless. Default format. |
jpeg | Email previews, social cards | Small | Lossy. No transparency support. |
webp | Link previews, web display | 30-40% smaller than PNG | Lossy or lossless. Universal browser support. |
avif | Long-term archiving, bandwidth-critical apps | Smallest | Best compression. Slower encoding on API side. |
tiff | Print production, pre-press | Very large | Uncompressed. Overkill for web use. |
pdf | Reports, contracts, legal evidence | Varies | Vector text, rasterized images. Separate PDF parameter set. |
WebP at quality 80-85 is my go-to for anything going on the web. Visually identical to PNG at a fraction of the file size. For archival work where fidelity matters more than bandwidth, PNG or AVIF are better picks. The full format breakdown is on the image format page.
# WebP at quality 85 — good balance of size and clarity
curl "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://example.com\
&format=webp\
&quality=85" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o screenshot.webp
Viewport and device settings
Default viewport is 1280x800, desktop Chrome on macOS. Override both dimensions or simulate mobile and tablet devices:
# Mobile viewport
curl "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://example.com\
&device=mobile\
&width=390\
&height=844" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o mobile.png
# Retina (2x) for high-DPI displays
curl "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://example.com\
&retina=true\
&width=1440" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o retina.png
Retina at 1440px width produces a 2880px-wide image. That's 4x the pixel count, 4x the file size. Fine for marketing materials and print, wasteful for thumbnails. Use resize_width to downscale after capture if you need a smaller output without losing the rendering benefits of a wide viewport.
The device preset also sets a matching User-Agent string, so responsive sites that sniff UA headers render the correct layout. For custom UA strings, pass user_agent directly.
Full-page URL to image capture
By default you get the visible viewport only. Add full_page=true to capture the entire scrollable height:
curl "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://example.com\
&full_page=true\
&delay=2" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o full.png
That delay=2 matters. Without it, images below the fold show up as gray boxes on almost every e-commerce site I've tested. Lazy loaders need time to fire after the scroll triggers their intersection observers. I covered the full list of failure modes — sticky headers, infinite scroll, SPA hydration — on the full-page screenshot page.
Cleaning up the page before capture
Cookie banners and chat widgets show up in every screenshot and obscure the content you actually want. Three parameters handle cleanup:
curl "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://example.com\
&block_cookies=true\
&block_ads=true\
&block_chats=true\
&hide_selectors[]=#promo-popup\
&hide_selectors[]=.newsletter-overlay" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o clean.png
block_cookies strips the most common consent managers automatically. block_ads removes ad iframes and tracking scripts. block_chats hides Intercom, Drift, Crisp, and similar widgets. For page-specific elements that don't fall into these categories, hide_selectors accepts any CSS selector.
All three default to true, so you get clean captures without thinking about it. Override to false when you specifically need to see what real users see.
Waiting for dynamic content
Getting the timing right on SPAs is the most frustrating part of screenshot automation. There's no universal setting that works everywhere, but two parameters cover most cases:
{
"url": "https://app.example.com/dashboard",
"wait_for_selector": ".chart-container canvas",
"delay": 2,
"timeout": 45
}
wait_for_selector pauses the capture until a CSS selector appears in the DOM. Pick something that only exists after the real content renders — a chart element, a data table row, a heading inside the main content area. Not the spinner.
delay adds a fixed pause (0-10 seconds) after network activity settles. timeout sets the overall limit (5-60 seconds, default 30). They stack: network idle first, then selector, then delay, then capture. I wrote a longer breakdown of waiting strategies if you're dealing with tricky timing.
Capturing pages behind authentication
Pass session cookies or custom headers to access logged-in pages:
curl "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://app.example.com/settings\
&cookies=[{\"name\":\"session\",\"value\":\"abc123\",\"domain\":\"app.example.com\"}]\
&headers={\"X-Auth-Token\":\"your-token\"}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o settings.png
The API injects them before navigation. Works for internal dashboards, staging environments, any page that requires a session. Browser context is destroyed after each request — credentials never persist or leak to subsequent captures. More details on the injection features page.
Anti-bot protection and stealth mode
Some sites block headless browsers outright. Cloudflare, PerimeterX, DataDome — they return a challenge page instead of real content. Your screenshot comes back showing "Checking your browser..." instead of the actual site.
stealth=true patches the browser to pass common bot-detection checks — Cloudflare's standard challenge, JS-based fingerprinting scripts, and most headless-browser sniffers. Not a silver bullet. Enterprise-grade WAFs with behavioral analysis still catch it. But for the 80% of sites running off-the-shelf protection, it works.
For region-locked content, geolocation and proxy route the request through a local IP.
URL to image vs HTML to image
The API accepts two input types. Same rendering pipeline, different starting points:
| URL to image | HTML to image | |
|---|---|---|
| Input | url=https://... | html=<html>...</html> |
| Use case | Capture existing pages | Render custom templates (invoices, OG images, certificates) |
| External resources | Loaded automatically | Must use absolute URLs or inline |
| JavaScript | Runs on the page | Runs if included in the HTML |
| Authentication | Cookies/headers supported | Not needed |
To convert a URL to an image of a live website — URL input. To generate images from templates you control — HTML input. There's also a Markdown input for simpler content like blog cards and documentation previews.
Common use cases
Link previews are where most people start. A user pastes a URL into your app, you call the API, display a thumbnail. Slack, Twitter, and Notion all do this. A website to image API handles the rendering so you don't have to run a browser on your server.
Need thumbnails for a directory of 500 sites? Website directories pass each URL through with a fixed viewport and resize_width for consistent, small images. Set cache_ttl to avoid re-rendering sites that haven't changed — the cache alone saved one of my early users 60% on their monthly quota.
Change monitoring and archiving are two sides of the same coin. Capture the same URL on a schedule, compare pixel diffs for regressions or competitor changes. For legal records, certified screenshots add SHA-256 hashes and timestamps. Pair with webhooks for fully automated pipelines.
Then there's OG image generation. Capture your own pages, resize to 1200x630, serve as og:image. No design tools, no manual exports.
URL to image code examples
The same url to screenshot API request in three languages. All return the image as a binary buffer.
// Node.js
const response = await fetch(
'https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&format=webp&quality=85',
{ headers: { Authorization: 'Bearer YOUR_API_KEY' } }
);
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync('screenshot.webp', buffer);
# Python
import requests
response = requests.get(
'https://api.screenshotrun.com/v1/screenshots/capture',
params={'url': 'https://example.com', 'format': 'webp', 'quality': 85},
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
with open('screenshot.webp', 'wb') as f:
f.write(response.content)
# cURL
curl "https://api.screenshotrun.com/v1/screenshots/capture?\
url=https://example.com\
&format=webp\
&quality=85" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o screenshot.webp
Full integration guides for Node.js, Python, PHP, Go, Java, Ruby, and cURL.
URL to image API parameters
Parameters most relevant to converting a webpage to image. The full list is in the API reference.
| Parameter | Type | Default | Description |
|---|---|---|---|
url | string | — | The page to capture. Required (unless using html or markdown). |
format | string | png | Output format: png, jpeg, webp, avif, tiff, pdf. |
quality | integer | 80 | Compression quality for lossy formats (1-100). |
width | integer | 1280 | Viewport width in pixels. |
height | integer | 800 | Viewport height in pixels. |
full_page | boolean | false | Capture the entire scrollable page. |
retina | boolean | false | 2x device pixel ratio. |
device | string | desktop | Device preset: desktop, mobile, tablet. |
delay | integer | 0 | Wait N seconds after page load (0-10). |
timeout | integer | 30 | Overall page load timeout in seconds (5-60). |
wait_for_selector | string | — | CSS selector to wait for before capture. |
block_cookies | boolean | true | Remove cookie consent banners. |
block_ads | boolean | true | Block ad networks and tracking scripts. |
block_chats | boolean | true | Hide live chat widgets. |
hide_selectors | array | — | CSS selectors to hide before capture. |
stealth | boolean | false | Bypass bot detection. |
dark_mode | boolean | false | Emulate prefers-color-scheme: dark. |
cache_ttl | integer | 0 | Cache duration in seconds. |
Start with three URLs you care about. Capture them in WebP at 1280px. That's your baseline. From there, layer on what you need: full-page capture, dark mode, scrolling video, element screenshots. Every feature uses the same url to image API endpoint and the same auth. The pricing page has the plan details.
FAQ#
The API supports PNG (default), JPEG, WebP, AVIF, TIFF, and PDF output. Set the format parameter to switch between them. WebP at quality 80-85 gives the best balance of file size and visual quality for web use.
Yes. The free tier includes 200 screenshots per month with full access to all parameters including full-page capture, format selection, and stealth mode. No credit card required to start.
Static sites typically render in 2-3 seconds. JavaScript-heavy SPAs with async data loading may take 6-10 seconds. The API monitors network activity and DOM mutations automatically to determine when the page is ready for capture.
Yes. Add full_page=true to capture the entire scrollable height of the page as one continuous image. Combine with delay=2 to ensure lazy-loaded images below the fold have time to render.
URL to image captures an existing live web page by navigating to it. HTML to image renders raw HTML markup you provide directly. Both use the same Chromium rendering pipeline and return the same output formats.