DEV Community

Cover image for How to Capture Website Screenshots with an API (Node.js, Python, cURL)
Alex Silverberg
Alex Silverberg

Posted on

How to Capture Website Screenshots with an API (Node.js, Python, cURL)

How to Capture Website Screenshots with an API (Node.js, Python, cURL)

If you've ever tried to capture website screenshots programmatically, you know the pain: spinning up headless Chrome, managing Puppeteer dependencies, handling timeouts, dealing with cookie banners, and watching your server's memory spike to 2GB.

There's a better way. Screenshot APIs let you offload all that complexity to a managed service. You send a URL, you get back an image. Simple.

In this guide, I'll show you how to capture screenshots, generate PDFs, and extract structured data from websites using SnapAPI — with working code examples in Node.js, Python, and cURL.

Why Use a Screenshot API?

Before we dive into code, let's talk about why you'd want this:

  • No infrastructure to manage — No headless Chrome, no Puppeteer updates, no memory issues
  • Cookie banner blocking — Automatically removes GDPR popups
  • Consistent rendering — Same result every time, on any device preset
  • Scales to millions — Your server doesn't need 8GB RAM per browser instance
  • Multiple formats — PNG, JPEG, WebP, AVIF from a single endpoint

If you're building link previews, generating social media cards, archiving web pages, or monitoring competitor sites — a screenshot API saves you weeks of development time.

Getting Started

First, grab a free API key from snapapi.pics. The free tier includes 100 screenshots/month with no credit card required.

Your API key will look like: sk_live_xxxxxxxxxxxx

All requests use the x-api-key header for authentication.

1. Capturing Screenshots

cURL

The simplest way to test:

curl -X POST "https://api.snapapi.pics/v1/screenshot" \
  -H "x-api-key: sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://github.com",
    "format": "png",
    "width": 1280,
    "height": 800
  }' \
  --output screenshot.png
Enter fullscreen mode Exit fullscreen mode

This captures a 1280x800 screenshot of GitHub's homepage and saves it as screenshot.png.

Node.js

const fs = require('fs');

async function captureScreenshot(url, options = {}) {
  const response = await fetch('https://api.snapapi.pics/v1/screenshot', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.SNAPAPI_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      url,
      format: options.format || 'png',
      width: options.width || 1280,
      height: options.height || 800,
      fullPage: options.fullPage || false,
      blockCookieBanners: true,
      blockAds: true,
    }),
  });

  if (!response.ok) {
    throw new Error(`Screenshot failed: ${response.status}`);
  }

  const buffer = Buffer.from(await response.arrayBuffer());
  fs.writeFileSync('screenshot.png', buffer);
  console.log('Screenshot saved!');
  return buffer;
}

// Usage
captureScreenshot('https://github.com', {
  format: 'webp',
  fullPage: true,
});
Enter fullscreen mode Exit fullscreen mode

Python

import requests
import os

def capture_screenshot(url, **kwargs):
    response = requests.post(
        'https://api.snapapi.pics/v1/screenshot',
        headers={
            'x-api-key': os.environ['SNAPAPI_KEY'],
            'Content-Type': 'application/json',
        },
        json={
            'url': url,
            'format': kwargs.get('format', 'png'),
            'width': kwargs.get('width', 1280),
            'height': kwargs.get('height', 800),
            'fullPage': kwargs.get('full_page', False),
            'blockCookieBanners': True,
            'blockAds': True,
        }
    )
    response.raise_for_status()

    with open('screenshot.png', 'wb') as f:
        f.write(response.content)
    print('Screenshot saved!')
    return response.content

# Usage
capture_screenshot('https://github.com', format='webp', full_page=True)
Enter fullscreen mode Exit fullscreen mode

2. Advanced Screenshot Options

SnapAPI supports a bunch of useful options:

{
  "url": "https://example.com",
  "format": "avif",
  "width": 1440,
  "height": 900,
  "fullPage": true,
  "devicePreset": "iPhone 15 Pro",
  "darkMode": true,
  "blockCookieBanners": true,
  "blockAds": true,
  "delay": 2000,
  "selector": "#main-content",
  "customCSS": "body { background: white; }",
  "customJS": "document.querySelector('.popup')?.remove();"
}
Enter fullscreen mode Exit fullscreen mode

Key features:

  • 26+ device presets — iPhone, iPad, Pixel, Galaxy, and more
  • AVIF format — 50-80% smaller files than PNG
  • Selector targeting — Screenshot just a specific element
  • Custom CSS/JS injection — Modify the page before capture
  • Dark mode — Render in dark color scheme

3. Generating PDFs

Same API, different endpoint:

async function generatePDF(url) {
  const response = await fetch('https://api.snapapi.pics/v1/screenshot', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.SNAPAPI_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      url,
      format: 'pdf',
      pdfFormat: 'A4',
      pdfPrintBackground: true,
      pdfMargin: { top: '1cm', bottom: '1cm', left: '1cm', right: '1cm' },
    }),
  });

  const buffer = Buffer.from(await response.arrayBuffer());
  require('fs').writeFileSync('page.pdf', buffer);
  console.log('PDF saved!');
}

generatePDF('https://example.com/invoice');
Enter fullscreen mode Exit fullscreen mode

PDF options include format (A4, Letter, Legal), margins, headers/footers, and background printing.

4. Extracting Structured Data

This is where it gets really interesting. The Extract API pulls structured data from any webpage — perfect for feeding into LLMs or building data pipelines:

async function extractData(url, type = 'structured') {
  const response = await fetch('https://api.snapapi.pics/v1/extract', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.SNAPAPI_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      url,
      type, // 'markdown', 'text', 'structured', 'metadata', 'links', 'images'
      cleanOutput: true,
      blockAds: true,
    }),
  });

  const data = await response.json();
  console.log(data);
  return data;
}

// Get clean markdown (great for LLMs)
extractData('https://dev.to', 'markdown');

// Get metadata (OG tags, title, description)
extractData('https://dev.to', 'metadata');

// Get all links on a page
extractData('https://dev.to', 'links');
Enter fullscreen mode Exit fullscreen mode

The structured type returns title, author, word count, and cleaned content — ideal for building RAG pipelines or content analysis tools.

Python Example

def extract_metadata(url):
    response = requests.post(
        'https://api.snapapi.pics/v1/extract',
        headers={
            'x-api-key': os.environ['SNAPAPI_KEY'],
            'Content-Type': 'application/json',
        },
        json={
            'url': url,
            'type': 'metadata',
        }
    )
    data = response.json()
    meta = data['data']

    print(f"Title: {meta['title']}")
    print(f"Description: {meta['description']}")
    print(f"OG Image: {meta['ogImage']}")
    return meta

extract_metadata('https://github.com')
Enter fullscreen mode Exit fullscreen mode

5. Real-World Use Cases

Link Previews (Like Slack)

Combine the Extract API for metadata + Screenshot API for thumbnails:

async function generateLinkPreview(url) {
  // Get metadata
  const metaResponse = await fetch('https://api.snapapi.pics/v1/extract', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.SNAPAPI_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ url, type: 'metadata' }),
  });
  const { data: meta } = await metaResponse.json();

  // Get screenshot thumbnail
  const screenshotResponse = await fetch('https://api.snapapi.pics/v1/screenshot', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.SNAPAPI_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      url,
      format: 'webp',
      width: 600,
      height: 400,
      blockCookieBanners: true,
    }),
  });

  return {
    title: meta.ogTitle || meta.title,
    description: meta.ogDescription || meta.description,
    image: meta.ogImage || screenshotResponse, // use OG image or fallback to screenshot
    favicon: meta.favicon,
    url,
  };
}
Enter fullscreen mode Exit fullscreen mode

SEO Monitoring

// Check competitor pages periodically
async function monitorPage(url) {
  const { data } = await extractData(url, 'metadata');

  return {
    title: data.title,
    description: data.description,
    h1Count: data.headings?.h1?.length || 0,
    canonical: data.canonical,
    ogImage: data.ogImage,
    timestamp: new Date().toISOString(),
  };
}
Enter fullscreen mode Exit fullscreen mode

Screenshot API Comparison

How does SnapAPI compare to alternatives?

Feature SnapAPI ScreenshotOne Urlbox ApiFlash
Free Tier 100/month 100/month None 100/month
Screenshot
PDF
Video
Data Extract
AVIF Format
Cookie Blocking
Device Presets 26+ 10+ 15+ 5
Starting Price $9/mo $29/mo $99/mo $29/mo

SnapAPI is the only API that combines screenshots, PDFs, video recording, and data extraction in a single service — so you don't need four different API subscriptions.

Error Handling Tips

Always handle errors gracefully:

async function safeScreenshot(url) {
  try {
    const response = await fetch('https://api.snapapi.pics/v1/screenshot', {
      method: 'POST',
      headers: {
        'x-api-key': process.env.SNAPAPI_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ url, format: 'png', timeout: 30000 }),
    });

    if (response.status === 429) {
      // Rate limited — wait and retry
      await new Promise(r => setTimeout(r, 2000));
      return safeScreenshot(url);
    }

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message);
    }

    return Buffer.from(await response.arrayBuffer());
  } catch (err) {
    console.error(`Screenshot failed for ${url}:`, err.message);
    return null;
  }
}
Enter fullscreen mode Exit fullscreen mode

Wrapping Up

Screenshot APIs save you from the headless browser nightmare. Instead of managing Puppeteer, Chrome dependencies, and memory issues, you get a simple REST API that handles everything.

SnapAPI stands out because it's four tools in one:

  1. 📸 Screenshots — PNG, JPEG, WebP, AVIF with 26+ device presets
  2. 📄 PDFs — A4, Letter, custom margins, headers/footers
  3. 🎬 Videos — Record browsing sessions (unique feature)
  4. 📊 Extract — Pull structured data, markdown, metadata from any page

Try It Free

Get 200 free screenshots per month at snapapi.pics. No credit card required.

The API is live and ready to use. If you run into any issues, the docs cover every parameter and edge case.


What screenshot use case are you building? Drop a comment below — I'd love to hear about it!

Top comments (0)