How to Capture Website Screenshots with an API
Capturing website screenshots programmatically is a common need for developers building social media tools, monitoring dashboards, PDF reports, or marketing automation. Instead of managing your own browser infrastructure, a screenshot API lets you capture any webpage with a single HTTP request.
This guide covers everything you need to know about website screenshot APIs -- what they are, how they work, and how to integrate one into your application with working code examples.
What Is a Website Screenshot API?
A website screenshot API is a web service that renders a URL in a headless browser and returns the result as an image (PNG, JPEG, WebP) or PDF. You send an HTTP request with the target URL and configuration options, and receive the screenshot back in the response body.
Key advantages over running your own browser:
- No infrastructure to manage: No need to install Chrome, maintain Docker containers, or handle browser crashes.
- Scales automatically: The API handles concurrent requests without you worrying about browser pools.
- Always up to date: The service keeps the browser engine current, so you always render pages correctly.
- Works from any language: If you can make an HTTP request, you can capture screenshots.
How Screenshot APIs Work
Behind the scenes, a screenshot API runs a pool of headless Chrome (or Chromium) browsers. When your request arrives, the service:
- Opens a new browser tab with the viewport size you specified
- Navigates to the target URL
- Waits for the page to fully load (including JavaScript rendering)
- Optionally waits additional time for lazy-loaded content
- Takes a screenshot in your chosen format
- Returns the image binary in the HTTP response
Getting Started with ScreenshotAPI
ScreenshotAPI provides a simple REST endpoint. Here is how to capture your first screenshot:
Step 1: Get Your API Key
Sign up for a free account to get your API key. The free tier includes 100 screenshots per month -- more than enough for testing and small projects.
Step 2: Make Your First Request
curl "https://screenshotapi-api-production.up.railway.app/v1/screenshot\
?url=https://example.com\
&width=1280&height=800\
&format=png" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o screenshot.pngThat is it. One request, one screenshot. The image is returned directly as binary data -- no polling, no callbacks, no webhooks needed.
Step 3: Customize Your Capture
The API supports many configuration options:
| Parameter | Description | Default |
|---|---|---|
url | Target URL (required) | -- |
width | Viewport width (320-3840) | 1280 |
height | Viewport height (200-2160) | 800 |
format | png, jpeg, or webp | png |
fullpage | Capture full scrollable page | false |
quality | JPEG/WebP quality (1-100) | 80 |
wait | Extra wait time in ms (0-10000) | 1000 |
Code Examples
Node.js
const fs = require('fs');
async function captureScreenshot(url, options = {}) {
const params = new URLSearchParams({
url,
format: options.format || 'png',
width: options.width || 1280,
height: options.height || 800,
fullpage: options.fullPage || false,
});
const response = await fetch(
`https://screenshotapi-api-production.up.railway.app/v1/screenshot?${params}`,
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error);
}
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync('screenshot.png', buffer);
console.log(`Screenshot saved! Size: ${buffer.length} bytes`);
console.log(`Render time: ${response.headers.get('X-Screenshot-Time-Ms')}ms`);
}
// Desktop screenshot
captureScreenshot('https://github.com');
// Mobile screenshot
captureScreenshot('https://github.com', { width: 375, height: 812, fullPage: true });Python
import requests
API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://screenshotapi-api-production.up.railway.app'
def capture(url, output='screenshot.png', **kwargs):
params = {'url': url, 'format': 'png', **kwargs}
headers = {'Authorization': f'Bearer {API_KEY}'}
response = requests.get(f'{BASE_URL}/v1/screenshot',
params=params, headers=headers)
response.raise_for_status()
with open(output, 'wb') as f:
f.write(response.content)
print(f'Saved {output} ({len(response.content)} bytes)')
print(f'Render time: {response.headers.get("X-Screenshot-Time-Ms")}ms')
# Capture a website
capture('https://example.com')
# Full page capture at mobile viewport
capture('https://example.com', output='mobile.png',
width=375, height=812, fullpage='true')PHP
<?php
$apiKey = 'YOUR_API_KEY';
$url = urlencode('https://example.com');
$ch = curl_init(
"https://screenshotapi-api-production.up.railway.app/v1/screenshot"
. "?url=$url&format=png&width=1280"
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer $apiKey"
]);
$screenshot = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
file_put_contents('screenshot.png', $screenshot);
echo "Screenshot saved!\n";
} else {
echo "Error: $screenshot\n";
}Common Use Cases
1. Social Media Link Previews
Generate Open Graph images for your pages dynamically. When someone shares your link on Twitter or LinkedIn, show a real screenshot of the page instead of a generic image.
2. Website Monitoring
Schedule periodic screenshots to detect visual regressions, broken layouts, or unauthorized changes. Compare screenshots over time to catch issues before your users do.
3. PDF Reports
Capture web dashboards or analytics pages as PDFs for stakeholder reports. Use the/v1/pdf endpoint for native PDF generation.
4. Thumbnail Generation
Build a directory or marketplace where you show previews of websites. Capture screenshots at smaller viewports for fast-loading thumbnails.
5. Automated Testing
Capture screenshots during end-to-end test runs for visual regression testing. Compare against baseline images to detect unintended UI changes.
API vs. Self-Hosted: Which Should You Choose?
| Factor | Screenshot API | Self-Hosted (Puppeteer) |
|---|---|---|
| Setup time | Minutes | Hours to days |
| Maintenance | None | Ongoing (Chrome updates, crashes) |
| Scaling | Automatic | Manual (Docker, Kubernetes) |
| Cost at low volume | Free | $20+/mo for a server |
| Cost at high volume | $29-99/mo | Variable (compute costs) |
| Customization | API parameters | Full control |
For most developers, an API is the right choice until you are taking more than 100,000 screenshots per month and need deep customization. Even then, many companies prefer APIs for reliability.
Best Practices
- Set appropriate wait times. Dynamic pages (React, Vue) may need 2-3 seconds of wait time after page load for JavaScript to render content.
- Use WebP for smaller files. WebP images are typically 25-30% smaller than PNG while maintaining quality.
- Cache your screenshots. If you are capturing the same URL repeatedly, cache the result for a reasonable TTL (1 hour to 24 hours).
- Handle errors gracefully. Some pages may block headless browsers or return errors. Always check the HTTP status code.
- Keep your API key server-side. Never expose your API key in frontend JavaScript. Make API calls from your backend.
Frequently Asked Questions
How fast are the screenshots?
Most screenshots complete in 2-5 seconds, depending on how quickly the target page loads. The render time is included in the X-Screenshot-Time-Ms response header.
Can I capture pages behind a login?
Not directly with a GET request. For authenticated pages, you would need to use a self-hosted solution like Puppeteer where you can set cookies or fill in forms.
What about JavaScript-heavy single-page apps?
The API uses a full headless Chrome browser, so JavaScript renders normally. Use the wait parameter to give the page extra time to render dynamic content.
Related Articles
Automate Website Screenshots with Node.js
Compare Puppeteer, Playwright, and API-based approaches for screenshot automation.
Try it yourself
Use our interactive playground to capture a screenshot right now -- no signup needed.
Open Playground