DEV Community

Custodia-Admin
Custodia-Admin

Posted on • Originally published at pagebolt.dev

Website Screenshot API: The Developer's Guide to Capturing Any Page

Website Screenshot API: The Developer's Guide to Capturing Any Page

Capturing website screenshots programmatically comes up constantly in developer workflows: visual regression testing, website monitoring, generating social preview cards, building PDFs from HTML, and increasingly — providing visual proof for AI agent actions.

You have two options: run Puppeteer (or Playwright) yourself, or call a screenshot API. This guide covers the API approach — what it is, when to use it, and how to call it from curl, Node.js, and Python.

Why a Screenshot API Instead of Puppeteer?

Self-hosting headless Chrome sounds simple but isn't:

  • Binary dependency hell — Chrome needs specific system libraries. Docker images bloat to 1–2 GB.
  • Memory leaks — Long-running Puppeteer processes consume memory and need restarts.
  • Blocked renders — Many sites detect headless Chrome and block it.
  • CAPTCHA / JS rendering — You're responsible for solving CAPTCHAs and waiting for dynamic content.
  • Maintenance — Chrome updates can break your setup unexpectedly.

A screenshot API handles all of this. You send a URL, get back an image.

The Simplest Possible Screenshot

curl "https://api.pagebolt.dev/v1/screenshot" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"url": "https://example.com"}' \
  -H "Content-Type: application/json" \
  --output screenshot.png
Enter fullscreen mode Exit fullscreen mode

Done. No Chrome. No dependencies. No Docker.

Node.js Example

const fs = require('fs');

async function screenshot(url, outputPath) {
  const response = await fetch('https://api.pagebolt.dev/v1/screenshot', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.PAGEBOLT_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      url,
      fullPage: true,
      blockBanners: true,
      blockAds: true
    })
  });

  const buffer = await response.arrayBuffer();
  fs.writeFileSync(outputPath, Buffer.from(buffer));
  console.log(`Screenshot saved to ${outputPath}`);
}

screenshot('https://example.com', 'output.png');
Enter fullscreen mode Exit fullscreen mode

Python Example

import requests
import os

def screenshot(url: str, output_path: str):
    response = requests.post(
        'https://api.pagebolt.dev/v1/screenshot',
        headers={
            'Authorization': f'Bearer {os.environ["PAGEBOLT_API_KEY"]}',
            'Content-Type': 'application/json'
        },
        json={
            'url': url,
            'fullPage': True,
            'blockBanners': True,
            'format': 'png'
        }
    )
    response.raise_for_status()
    with open(output_path, 'wb') as f:
        f.write(response.content)
    print(f'Screenshot saved to {output_path}')

screenshot('https://example.com', 'output.png')
Enter fullscreen mode Exit fullscreen mode

Common Use Cases

1. Website Monitoring

Capture a daily screenshot to detect visual changes — layout breaks, content changes, error pages.

const cron = require('node-cron');

cron.schedule('0 9 * * *', async () => {
  const date = new Date().toISOString().split('T')[0];
  await screenshot('https://yourapp.com', `snapshots/${date}.png`);
});
Enter fullscreen mode Exit fullscreen mode

2. Open Graph / Social Preview Images

Generate og:image cards dynamically so every blog post and product page looks sharp when shared on LinkedIn, Twitter, or Slack.

const response = await fetch('https://api.pagebolt.dev/v1/screenshot', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.PAGEBOLT_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: `https://yourapp.com/og-template?title=${encodeURIComponent(post.title)}`,
    viewportWidth: 1200,
    viewportHeight: 630,
    format: 'jpeg',
    quality: 90
  })
});
Enter fullscreen mode Exit fullscreen mode

3. HTML to PDF

Render invoices, reports, and certificates from HTML templates.

const response = await fetch('https://api.pagebolt.dev/v1/pdf', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.PAGEBOLT_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    html: `<html><body><h1>Invoice #${id}</h1>...</body></html>`,
    pdfOptions: { format: 'A4' }
  })
});
Enter fullscreen mode Exit fullscreen mode

4. AI Agent Visual Proof

When an AI agent completes a browser task, capture a screenshot as evidence. This is critical for compliance workflows — you need to prove the agent did what it was supposed to do.

// After agent completes a task
const evidence = await fetch('https://api.pagebolt.dev/v1/screenshot', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.PAGEBOLT_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: currentUrl,
    metadata: { agentId, taskId, timestamp: Date.now() }
  })
});
// Store the binary + metadata for the audit trail
Enter fullscreen mode Exit fullscreen mode

5. Visual Regression Testing in CI

Capture screenshots before and after a deploy, diff them with a tool like pixelmatch or resemblejs.

# .github/workflows/visual-test.yml
- name: Capture post-deploy screenshot
  run: |
    curl -s -X POST https://api.pagebolt.dev/v1/screenshot \
      -H "Authorization: Bearer ${{ secrets.PAGEBOLT_API_KEY }}" \
      -H "Content-Type: application/json" \
      -d '{"url": "https://staging.yourapp.com", "fullPage": true}' \
      --output post-deploy.png
Enter fullscreen mode Exit fullscreen mode

Full-Page vs Viewport Screenshots

  • fullPage: true — captures the entire scrollable page, even content below the fold. Best for content pages and documentation.
  • Default (no fullPage) — captures only the visible viewport. Best for above-the-fold social cards and hero images.

Blocking Noise

Most pages have banners, ads, and chat widgets that pollute screenshots. Block them:

{
  "url": "https://example.com",
  "blockBanners": true,
  "blockAds": true,
  "blockChats": true,
  "blockTrackers": true
}
Enter fullscreen mode Exit fullscreen mode

Device Emulation

Capture how a page looks on mobile, tablet, or a specific device:

body: JSON.stringify({
  url: 'https://example.com',
  viewportDevice: 'iphone_14_pro'
})
Enter fullscreen mode Exit fullscreen mode

Get the full list of supported devices with:

curl "https://api.pagebolt.dev/v1/devices" \
  -H "Authorization: Bearer YOUR_API_KEY"
Enter fullscreen mode Exit fullscreen mode

Authenticated Pages

For pages behind login, pass session cookies:

body: JSON.stringify({
  url: 'https://app.yourservice.com/dashboard',
  cookies: [
    { name: 'session', value: process.env.SESSION_TOKEN, domain: 'app.yourservice.com' }
  ]
})
Enter fullscreen mode Exit fullscreen mode

Handling the Response

By default, the API returns binary image data. For programmatic workflows, use response_type: "json" to get a base64 payload:

body: JSON.stringify({
  url: 'https://example.com',
  response_type: 'json'
})

// Response: { "image": "base64string...", "metadata": { ... } }
Enter fullscreen mode Exit fullscreen mode

Free Tier

PageBolt includes 100 screenshot requests per month on the free tier — no credit card required. It's enough to explore every feature and prototype your integration before committing.

Get started: pagebolt.dev

Top comments (0)