← Til baka

How to Take Website Screenshots in Node.js (3 Methods Compared)

· 5 mín lestrartími · Almennt

The Problem: Capturing Websites Programmatically

You're building a SaaS app and need link previews. Or a monitoring dashboard with visual diffs. Or automated reports with embedded page captures. Whatever the use case, you need to turn URLs into images — reliably, at scale.

Here are 3 approaches, from DIY to fully managed, with real code you can use today.

Method 1: Puppeteer (Self-Hosted)

Puppeteer is Google's official Node.js library for controlling headless Chrome. It gives you full control but requires managing browser instances yourself.

const puppeteer = require('puppeteer');

async function takeScreenshot(url, outputPath) {
  const browser = await puppeteer.launch({
    headless: 'new',
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  });
  const page = await browser.newPage();
  await page.setViewport({ width: 1280, height: 800 });
  await page.goto(url, { waitUntil: 'networkidle2' });
  await page.screenshot({ path: outputPath, type: 'png' });
  await browser.close();
}

Pros: Full control, free, can interact with pages before capture.
Cons: Resource-heavy (~200MB RAM per browser), needs server management, crashes under load, Chrome updates can break things.

Method 2: Playwright (Self-Hosted, Multi-Browser)

Microsoft's Playwright supports Chrome, Firefox, and WebKit. Similar to Puppeteer but with better cross-browser support.

const { chromium } = require('playwright');

async function takeScreenshot(url, outputPath) {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.setViewportSize({ width: 1280, height: 800 });
  await page.goto(url, { waitUntil: 'networkidle' });
  await page.screenshot({ path: outputPath });
  await browser.close();
}

Pros: Multi-browser, better API design, auto-wait features.
Cons: Same resource overhead as Puppeteer, larger install size.

Method 3: Screenshot API (Managed Service)

Skip the infrastructure. Send a GET request, get an image back. Here's how with Pandan Screenshot API:

const https = require('https');
const fs = require('fs');

const url = 'https://api.pandan.is/v1/screenshot?url=https://github.com&width=1920&format=png';

https.get(url, (res) => {
  const stream = fs.createWriteStream('screenshot.png');
  res.pipe(stream);
  stream.on('finish', () => console.log('Screenshot saved!'));
});

// Or with fetch (Node 18+)
const response = await fetch(
  'https://api.pandan.is/v1/screenshot?url=https://github.com'
);
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync('screenshot.png', buffer);

Pros: No server to manage, no Chrome crashes, scales automatically, under 3 seconds.
Cons: External dependency, rate limits on free tier.

Comparison Table

FeaturePuppeteerPlaywrightAPI
Setup time30 min30 min0 min
Server neededYesYesNo
RAM per instance~200MB~200MB0
Concurrent captures~5-10/server~5-10/serverUnlimited
Full page captureYesYesYes
PDF generationYesYesYes
Cost at 1K/mo$5-20 (server)$5-20 (server)$9 (Pandan)

When to Use Each

Bonus: Generate PDFs Too

Need PDFs instead of images? All three methods support it:

// Pandan API — one line
curl "https://api.pandan.is/v1/pdf?url=https://example.com&format=A4" -o page.pdf

// Puppeteer
await page.pdf({ path: 'page.pdf', format: 'A4' });

// Playwright
await page.pdf({ path: 'page.pdf', format: 'A4' });

The API approach is especially useful for PDFs since Chrome's PDF rendering can be memory-intensive — let someone else handle the infrastructure.

Get Started

Try the Pandan Screenshot API free — 100 screenshots per month, no credit card, no SDK required. Just a GET request.