How to Take Website Screenshots
with Node.js
There are three main approaches: run a headless browser yourself (Puppeteer/Playwright), use a managed API (GrabShot), or use a cloud browser service. Here's how each works, with code you can copy and paste.
1. Puppeteer (Self-Hosted)
Puppeteer controls a headless Chrome instance on your server. It's free and gives you full control, but you need to manage Chrome, memory, and scaling yourself.
npm install puppeteer
const puppeteer = require('puppeteer');
async function screenshot(url, outputPath) {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 900 });
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
await page.screenshot({ path: outputPath, type: 'png' });
await browser.close();
}
screenshot('https://github.com', 'github.png');
Pros: Free, full control, can interact with pages.
Cons: Uses 200-500MB RAM per browser instance. Crashes on high load. You handle scaling, timeouts, and zombie processes.
2. GrabShot API (Managed)
GrabShot runs the headless browser for you. One HTTP request returns a screenshot. No Chrome to manage, no server to maintain.
// No npm install needed - it's just an HTTP request
async function screenshot(url) {
const apiKey = 'YOUR_API_KEY'; // Get free at grabshot.dev
const response = await fetch(
`https://grabshot.dev/v1/screenshot?` + new URLSearchParams({
url,
format: 'webp',
width: '1440',
apiKey
})
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}
return Buffer.from(await response.arrayBuffer());
}
// Usage
const img = await screenshot('https://github.com');
fs.writeFileSync('github.webp', img);
Pros: Zero infrastructure. Works from any environment (serverless, edge, CI). AI cleanup removes cookie banners. Device frame mockups built in.
Cons: 25 free/month, then $9/mo for 2,500.
Full-page + device frame example:
const url = `https://grabshot.dev/v1/screenshot?` + new URLSearchParams({
url: 'https://stripe.com',
fullPage: 'false',
deviceFrame: 'macbook-air',
aiCleanup: 'true',
format: 'png',
apiKey: 'YOUR_KEY'
});
// Returns a screenshot of Stripe inside a MacBook Air frame,
// with cookie banners and popups removed by AI
3. Playwright
Playwright is similar to Puppeteer but supports multiple browsers (Chrome, Firefox, WebKit) and has better auto-waiting.
npm install playwright
const { chromium } = require('playwright');
async function screenshot(url, outputPath) {
const browser = await chromium.launch();
const page = await browser.newPage({
viewport: { width: 1440, height: 900 }
});
await page.goto(url, { waitUntil: 'networkidle' });
await page.screenshot({ path: outputPath, type: 'png' });
await browser.close();
}
screenshot('https://github.com', 'github.png');
Pros: Multi-browser support, better waiting strategies, active development.
Cons: Same scaling challenges as Puppeteer. Larger install size (~400MB).
Comparison
| Feature | Puppeteer | GrabShot API | Playwright |
|---|---|---|---|
| Setup time | 5-30 min | 30 seconds | 5-30 min |
| Infrastructure needed | Server with Chrome | None | Server with browsers |
| Cost | Server costs | Free tier, then $9/mo | Server costs |
| Device frames | DIY | Built-in | DIY |
| AI popup removal | No | Yes | No |
| Serverless friendly | Difficult | Yes | Difficult |
| Page interaction | Full control | Limited | Full control |
See it in action
Try GrabShot right now — paste any URL and get a screenshot instantly. No signup needed.
Try Free Screenshot Tool →