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
100 renders / month, no credit card. Or buy credits one-time and use them whenever — credits never expire.
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