Need to capture website screenshots programmatically? Here is how to build your own screenshot API using Node.js and Puppeteer.
Why Screenshot APIs?
Common use cases:
- Social media previews - Generate OG images from any URL
- PDF reports - Convert HTML dashboards to PDF
- Visual regression testing - Catch UI bugs before deploy
- Monitoring - Track visual changes on competitor sites
- Documentation - Auto-generate screenshots for docs
The Stack
Node.js + Express + Puppeteer + @sparticuz/chromium
Step 1: Setup
mkdir screenshot-api && cd screenshot-api
npm init -y
npm install express puppeteer-core @sparticuz/chromium
Step 2: Basic Screenshot Endpoint
const express = require("express");
const chromium = require("@sparticuz/chromium");
const puppeteer = require("puppeteer-core");
const app = express();
app.get("/screenshot", async (req, res) => {
const { url, width = 1280, height = 720 } = req.query;
if (!url) return res.status(400).json({ error: "URL required" });
const browser = await puppeteer.launch({
args: chromium.args,
executablePath: await chromium.executablePath(),
headless: chromium.headless,
});
const page = await browser.newPage();
await page.setViewport({ width: +width, height: +height });
await page.goto(url, { waitUntil: "networkidle0" });
const screenshot = await page.screenshot({ type: "png" });
await browser.close();
res.type("image/png").send(screenshot);
});
app.listen(3000);
Step 3: Add PDF Generation
app.get("/pdf", async (req, res) => {
const { url } = req.query;
// ... browser setup same as above
const pdf = await page.pdf({ format: "A4" });
await browser.close();
res.type("application/pdf").send(pdf);
});
Step 4: Deploy to Vercel
Use @sparticuz/chromium-min for Vercel serverless:
npm install @sparticuz/chromium-min
This keeps the bundle under Vercel 50MB limit.
Or Just Use an API
If you do not want to maintain your own infrastructure, CaptureAPI handles screenshots, PDFs, and OG images with a single endpoint. Free tier: 200 captures/month.
curl "https://captureapi.dev/api/screenshot?url=https://example.com"
Full source code and docs at captureapi.dev
Top comments (0)