📋 Table of Contents
When to Use JavaScript for Screenshots
JavaScript is the language of the web. Whether you're building a Node.js backend or a React frontend, you'll eventually need to capture screenshots for:
- Link previews - Like Slack, Discord, Twitter
- Social share images - Dynamic OG images
- PDF reports - Generate reports from web dashboards
- Testing - Visual regression testing
- Archiving - Website snapshots
Method 1: Puppeteer (Node.js)
Puppeteer is Google's official headless Chrome library. It's powerful but requires Chrome on your server.
Installation
npm install puppeteer
Basic Screenshot
const puppeteer = require('puppeteer');
async function takeScreenshot(url, filename) {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.setViewport({ width: 1920, height: 1080 });
await page.goto(url, { waitUntil: 'networkidle0' });
await page.screenshot({ path: filename });
await browser.close();
console.log(`Screenshot saved: ${filename}`);
}
takeScreenshot('https://example.com', 'screenshot.png');
Full Page Screenshot
await page.screenshot({
path: 'fullpage.png',
fullPage: true
});
Specific Element Screenshot
const element = await page.$('.hero-section');
await element.screenshot({ path: 'element.png' });
Method 2: Playwright (Node.js)
Playwright is Microsoft's modern alternative with better TypeScript support and cross-browser testing.
Installation
npm install playwright
Basic Screenshot
const { chromium } = require('playwright');
async function takeScreenshot(url, filename) {
const browser = await chromium.launch();
const page = await browser.newPage({
viewport: { width: 1920, height: 1080 }
});
await page.goto(url, { waitUntil: 'networkidle' });
await page.screenshot({ path: filename });
await browser.close();
}
takeScreenshot('https://example.com', 'screenshot.png');
Method 3: Screenshot API (Easiest)
The simplest method is using a Screenshot API. No Chrome installation, no dependencies - works everywhere including serverless.
Using fetch (Native Node.js 18+)
async function takeScreenshot(url, filename) {
const apiKey = 'your-api-key';
const apiUrl = new URL('https://snapapi.alterra-solutions.com/v1/screenshot');
apiUrl.searchParams.set('url', url);
apiUrl.searchParams.set('api_key', apiKey);
apiUrl.searchParams.set('width', '1920');
apiUrl.searchParams.set('height', '1080');
apiUrl.searchParams.set('response', 'binary');
const response = await fetch(apiUrl);
const buffer = await response.arrayBuffer();
const fs = require('fs');
fs.writeFileSync(filename, Buffer.from(buffer));
console.log(`Screenshot saved: ${filename}`);
}
takeScreenshot('https://example.com', 'screenshot.png');
Using node-fetch (Older Node.js)
const fetch = require('node-fetch');
const fs = require('fs');
async function takeScreenshot(url, filename) {
const apiKey = process.env.SNAPAPI_KEY;
const endpoint = `https://snapapi.alterra-solutions.com/v1/screenshot`;
const params = new URLSearchParams({
url,
api_key: apiKey,
response: 'binary',
width: '1920',
height: '1080'
});
const response = await fetch(`${endpoint}?${params}`);
const buffer = await response.buffer();
fs.writeFileSync(filename, buffer);
console.log(`✅ Screenshot saved: ${filename}`);
}
takeScreenshot('https://github.com', 'github.png');
✅ Why use an API?
- No Chrome/Chromium installation needed
- Works in Vercel, Netlify, AWS Lambda
- Consistent results across environments
- 100 free screenshots per month
Browser-Based Screenshots
In the browser, you can use the API directly with fetch:
React Component Example
import { useState } from 'react';
function ScreenshotPreview({ url }) {
const [imageUrl, setImageUrl] = useState(null);
const [loading, setLoading] = useState(false);
const captureScreenshot = async () => {
setLoading(true);
const apiUrl = new URL('https://snapapi.alterra-solutions.com/v1/screenshot');
apiUrl.searchParams.set('url', url);
apiUrl.searchParams.set('api_key', process.env.REACT_APP_SNAPAPI_KEY);
apiUrl.searchParams.set('response', 'binary');
const response = await fetch(apiUrl);
const blob = await response.blob();
const objectUrl = URL.createObjectURL(blob);
setImageUrl(objectUrl);
setLoading(false);
};
return (
<div>
<button onClick={captureScreenshot} disabled={loading}>
{loading ? 'Capturing...' : 'Capture Screenshot'}
</button>
{imageUrl && <img src={imageUrl} alt="Screenshot" />}
</div>
);
}
Framework Examples
Express.js API Endpoint
const express = require('express');
const app = express();
app.get('/api/screenshot', async (req, res) => {
const { url } = req.query;
if (!url) {
return res.status(400).json({ error: 'URL required' });
}
try {
const apiUrl = new URL('https://snapapi.alterra-solutions.com/v1/screenshot');
apiUrl.searchParams.set('url', url);
apiUrl.searchParams.set('api_key', process.env.SNAPAPI_KEY);
apiUrl.searchParams.set('response', 'binary');
const response = await fetch(apiUrl);
const buffer = await response.arrayBuffer();
res.set('Content-Type', 'image/png');
res.set('Cache-Control', 'public, max-age=3600');
res.send(Buffer.from(buffer));
} catch (error) {
res.status(500).json({ error: 'Failed to capture' });
}
});
app.listen(3000);
Next.js API Route
// pages/api/screenshot.js
export default async function handler(req, res) {
const { url } = req.query;
const apiUrl = new URL('https://snapapi.alterra-solutions.com/v1/screenshot');
apiUrl.searchParams.set('url', url);
apiUrl.searchParams.set('api_key', process.env.SNAPAPI_KEY);
apiUrl.searchParams.set('response', 'binary');
const response = await fetch(apiUrl);
const buffer = await response.arrayBuffer();
res.setHeader('Content-Type', 'image/png');
res.setHeader('Cache-Control', 's-maxage=3600');
res.send(Buffer.from(buffer));
}
Start Capturing Screenshots
Get your free API key - 100 screenshots per month included.
Get Free API Key →