Taking screenshots of websites programmatically is one of those tasks that sounds simple until you actually try it. You need Puppeteer or Playwright, a headless Chromium binary, proper error handling for timeouts and navigation failures, and a server with enough memory to run a browser.
Or... you can make one API call.
The Hard Way (Puppeteer)
// First: npm install puppeteer (downloads 300MB+ Chromium)
const puppeteer = require('puppeteer');
async function screenshot(url) {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 720 });
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
const buffer = await page.screenshot({ type: 'png' });
await browser.close();
return buffer;
}
This works locally, but deploying it is painful. Chromium needs 400MB+ of disk, ~500MB RAM per instance, and crashes unpredictably on cheap VPS/serverless platforms.
The Easy Way (One API Call)
curl "https://agent-gateway-kappa.vercel.app/v1/agent-screenshot/api/screenshot?url=https://github.com" \
-H "X-Api-Key: YOUR_API_KEY" \
-o screenshot.png
That's it. You get back a PNG image. No browser installation, no memory management, no timeout debugging.
Getting Started
First, grab a free API key (200 free credits, no credit card):
curl -X POST https://agent-gateway-kappa.vercel.app/api/keys/create
Response:
{
"key": "gw_abc123...",
"credits": 200,
"expiresAt": "2026-04-03T..."
}
Each screenshot costs 1 credit. That's 200 screenshots to try it out.
JavaScript Example
const fs = require('fs');
async function takeScreenshot(url, options = {}) {
const params = new URLSearchParams({
url,
viewport: options.viewport || 'desktop',
format: options.format || 'png',
...(options.fullPage && { fullPage: 'true' }),
...(options.darkMode && { darkMode: 'true' })
});
const response = await fetch(
`https://agent-gateway-kappa.vercel.app/v1/agent-screenshot/api/screenshot?${params}`,
{ headers: { 'X-Api-Key': process.env.API_KEY } }
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Screenshot failed');
}
return Buffer.from(await response.arrayBuffer());
}
// Usage
const screenshot = await takeScreenshot('https://github.com');
fs.writeFileSync('github.png', screenshot);
console.log('Saved screenshot (${screenshot.length} bytes)');
Python Example
import requests
API_KEY = "your_api_key_here"
BASE_URL = "https://agent-gateway-kappa.vercel.app"
def take_screenshot(url, viewport="desktop", format="png", full_page=False):
response = requests.get(
f"{BASE_URL}/v1/agent-screenshot/api/screenshot",
params={
"url": url,
"viewport": viewport,
"format": format,
"fullPage": str(full_page).lower()
},
headers={"X-Api-Key": API_KEY}
)
response.raise_for_status()
return response.content
# Take a desktop screenshot
image = take_screenshot("https://news.ycombinator.com")
with open("hn.png", "wb") as f:
f.write(image)
print(f"Saved {len(image)} bytes")
Advanced: POST for More Options
The GET endpoint covers most cases, but POST gives you full control:
curl -X POST https://agent-gateway-kappa.vercel.app/v1/agent-screenshot/api/screenshot \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"viewport": "mobile",
"fullPage": true,
"format": "png",
"darkMode": true,
"delay": 2000,
"hideSelectors": [".cookie-banner", "#popup"],
"timeout": 15000
}' \
-o screenshot.png
Available Options
| Parameter | Type | Default | Description |
|---|---|---|---|
url |
string | required | URL to capture |
viewport |
string | desktop |
desktop (1280x720), mobile (375x812), tablet (768x1024) |
fullPage |
boolean | false |
Capture the entire scrollable page |
format |
string | png |
png or jpeg
|
quality |
number | 80 |
JPEG quality (1-100) |
darkMode |
boolean | false |
Emulate dark mode |
delay |
number | 0 |
Wait N ms after page load before capturing (max 5000) |
hideSelectors |
array | [] |
CSS selectors to hide (cookie banners, popups, etc.) |
selector |
string | null |
Capture only a specific element |
timeout |
number | 15000 |
Navigation timeout in ms (max 30000) |
Real-World Use Cases
1. Social Media Preview Cards
Generate Open Graph images for your blog posts dynamically:
app.get('/og-image', async (req, res) => {
const { title } = req.query;
// Create a simple HTML page with the title styled
const htmlUrl = `https://yoursite.com/og-template?title=${encodeURIComponent(title)}`;
const image = await takeScreenshot(htmlUrl, { viewport: 'desktop' });
res.set('Content-Type', 'image/png');
res.set('Cache-Control', 'public, max-age=86400');
res.send(image);
});
2. Visual Regression Testing
Compare screenshots before and after deployments:
import hashlib
def check_visual_regression(url):
current = take_screenshot(url)
current_hash = hashlib.md5(current).hexdigest()
try:
with open("baseline.png", "rb") as f:
baseline_hash = hashlib.md5(f.read()).hexdigest()
except FileNotFoundError:
# First run — save as baseline
with open("baseline.png", "wb") as f:
f.write(current)
return "baseline_saved"
if current_hash != baseline_hash:
with open("current.png", "wb") as f:
f.write(current)
return "visual_change_detected"
return "no_changes"
result = check_visual_regression("https://yoursite.com")
print(result)
3. Monitoring Dashboard
Take periodic screenshots of your services:
const services = [
'https://yourapp.com',
'https://yourapp.com/dashboard',
'https://yourapp.com/status',
];
for (const url of services) {
const image = await takeScreenshot(url);
const name = new URL(url).pathname.replace(/\//g, '_') || 'home';
fs.writeFileSync(`monitoring/${name}_${Date.now()}.png`, image);
}
Response Headers
The API returns useful metadata in response headers:
Content-Type: image/png
X-Screenshot-Id: scr_a1b2c3d4e5f6
X-Page-Title: GitHub%3A%20Let%27s%20build%20from%20here
X-Image-Size: 84521
X-Page-Title is URL-encoded and gives you the page's <title> tag — useful for logging or display without parsing HTML.
Pricing
- 200 free screenshots with a new API key (no credit card)
- After that: 1 credit per screenshot
- Top up with USDC on Base or Monero (XMR) — pricing details
The same API key works across 40+ other APIs (geolocation, DNS lookup, crypto prices, web scraping, and more) — check the full catalog.
Get your free API key:
curl -X POST https://agent-gateway-kappa.vercel.app/api/keys/create
Full API docs: agent-gateway-kappa.vercel.app/docs
Top comments (0)