URL to Image API

Convert any URL to a PNG, JPEG, WebP, or AVIF image with one API call. Real Chromium rendering, full-page capture, stealth mode, and 200 free screenshots/month.

Vitalii Holben Updated

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:

FormatBest forFile sizeNotes
pngVisual regression testing, compliance recordsLargestLossless. Default format.
jpegEmail previews, social cardsSmallLossy. No transparency support.
webpLink previews, web display30-40% smaller than PNGLossy or lossless. Universal browser support.
avifLong-term archiving, bandwidth-critical appsSmallestBest compression. Slower encoding on API side.
tiffPrint production, pre-pressVery largeUncompressed. Overkill for web use.
pdfReports, contracts, legal evidenceVariesVector 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 imageHTML to image
Inputurl=https://...html=<html>...</html>
Use caseCapture existing pagesRender custom templates (invoices, OG images, certificates)
External resourcesLoaded automaticallyMust use absolute URLs or inline
JavaScriptRuns on the pageRuns if included in the HTML
AuthenticationCookies/headers supportedNot 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.

ParameterTypeDefaultDescription
urlstring—The page to capture. Required (unless using html or markdown).
formatstringpngOutput format: png, jpeg, webp, avif, tiff, pdf.
qualityinteger80Compression quality for lossy formats (1-100).
widthinteger1280Viewport width in pixels.
heightinteger800Viewport height in pixels.
full_pagebooleanfalseCapture the entire scrollable page.
retinabooleanfalse2x device pixel ratio.
devicestringdesktopDevice preset: desktop, mobile, tablet.
delayinteger0Wait N seconds after page load (0-10).
timeoutinteger30Overall page load timeout in seconds (5-60).
wait_for_selectorstring—CSS selector to wait for before capture.
block_cookiesbooleantrueRemove cookie consent banners.
block_adsbooleantrueBlock ad networks and tracking scripts.
block_chatsbooleantrueHide live chat widgets.
hide_selectorsarray—CSS selectors to hide before capture.
stealthbooleanfalseBypass bot detection.
dark_modebooleanfalseEmulate prefers-color-scheme: dark.
cache_ttlinteger0Cache 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.

Written by

Vitalii Holben

Co-founder and CEO of ScreenshotRun. Full-stack developer building screenshot API tools that help developers capture, automate, and monitor web pages at scale. Based in Europe, shipping code since 201...

Screenshot API in a few clicks

Free plan includes 200 screenshots every month. No credit card required.

Sign up → copy your key → make your first call