Take Website Screenshots with Code: One API Call, No Puppeteer Setup

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • MyrinNew
    Senior Member
    • Feb 2024
    • 5168

    #1

    Take Website Screenshots with Code: One API Call, No Puppeteer Setup

    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.a...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

    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 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




    More...
Working...