Take Website Screenshots in Node.js: A Complete Tutorial
Taking screenshots in Node.js usually means wrestling with Puppeteer: installing Chromium, managing browser instances, dealing with memory leaks. This guide shows you a simpler approach that works from any Node.js environment — including AWS Lambda, Vercel, and Cloudflare Workers.
Install the SDK
npm install screenshotapis
That's the only dependency. No Chromium download, no system libraries, no Dockerfile changes.
Your first screenshot
import Client from "screenshotapis";
const client = new Client("sk_live_your_key");
const { data } = await client.screenshot({
url: "https://example.com",
format: "png",
full_page: true,
});
import { writeFileSync } from "fs";
writeFileSync("screenshot.png", data);
That's the complete example. The SDK handles authentication, request serialization, and returns a Buffer you can write to disk or stream to S3.
Common patterns
Screenshot a user-provided URL safely
If you're letting users input URLs (e.g., link previews in a chat app), the API automatically rejects internal IPs and localhost to prevent SSRF attacks. You don't need to add your own validation.
app.post("/preview", async (req, res) => {
const { url } = req.body;
try {
const { data } = await client.screenshot({ url, format: "webp" });
res.type("image/webp").send(data);
} catch (err) {
res.status(400).json({ error: "Could not render URL" });
}
});
Generate OG images from templates
Send HTML instead of a URL to render dynamic social media preview cards:
const html = `
<div style="width:1200px;height:630px;background:#1e3a8a;color:#fff;
display:flex;align-items:center;justify-content:center;
font-family:system-ui;font-size:48px">
${postTitle}
</div>
`;
const { data } = await client.screenshot({
html,
selector: "div",
device_scale_factor: 2,
});
Async rendering with webhooks
For large full-page screenshots or batch jobs, use webhook callbacks to avoid blocking:
await client.screenshot({
url: "https://huge-page.com",
full_page: true,
webhook_url: "https://your-app.com/webhooks/screenshot",
});
// Returns immediately with 202 Accepted
// Your webhook receives the result when rendering completes
Works on serverless out of the box
Because there's no browser to launch, this works on platforms where Puppeteer doesn't — or requires special builds:
- Vercel serverless functions — no 50MB function size limit issues
- AWS Lambda — no Chromium layer needed
- Cloudflare Workers — works within the 10ms CPU budget for non-render work
- Netlify Functions — fits in the 250MB unzipped limit with room to spare
Performance tips
- Use
format: "webp"for 30% smaller files vs PNG - Set
wait_until: "domcontentloaded"for faster renders when you don't need network-idle - Cache results in Redis/Cloudflare KV — screenshots of the same URL rarely change minute-to-minute
- Use
block_ads: trueto skip loading ad scripts (faster renders, cleaner screenshots)
Start capturing screenshots in Node.js — no browser needed
Get your API key — free