Quick Start with Fetch
Node.js 18+ includes a built-in fetch API, making SnapAPI integration trivial with zero dependencies:
const API_KEY = process.env.SNAPAPI_KEY;
async function screenshot(url, opts = {}) {
const params = new URLSearchParams({
url,
format: opts.format || 'png',
width: String(opts.width || 1280),
height: String(opts.height || 800),
});
if (opts.fullPage) params.set('full_page', 'true');
if (opts.darkMode) params.set('dark_mode', 'true');
const res = await fetch(
`https://apisnap.dev/api/screenshot?${params}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
if (!res.ok) {
const err = await res.json();
throw new Error(err.error || 'Screenshot failed');
}
return Buffer.from(await res.arrayBuffer());
}
// Usage
const image = await screenshot('https://github.com');
fs.writeFileSync('github.png', image);Using Axios
If your project already uses axios, the integration is equally straightforward:
import axios from 'axios';
import fs from 'fs';
const snap = axios.create({
baseURL: 'https://apisnap.dev/api',
headers: { Authorization: `Bearer ${process.env.SNAPAPI_KEY}` },
responseType: 'arraybuffer',
});
const { data } = await snap.get('/screenshot', {
params: { url: 'https://stripe.com', format: 'jpeg', quality: 85 }
});
fs.writeFileSync('stripe.jpg', data);
console.log('Remaining:', res.headers['x-usage-remaining']);
The x-usage-remaining header tells you how many screenshots remain in your monthly quota.
Start Capturing Screenshots Today
100 free screenshots per month. No credit card required. API key delivered instantly.
Get Started FreeExpress Integration
Build a screenshot proxy endpoint in your Express app to generate screenshots on demand:
import express from 'express';
const app = express();
app.get('/preview', async (req, res) => {
const { url } = req.query;
if (!url) return res.status(400).json({ error: 'URL required' });
try {
const ssRes = await fetch(
`https://apisnap.dev/api/screenshot?url=${encodeURIComponent(url)}&format=png&width=1200&height=630`,
{ headers: { Authorization: `Bearer ${process.env.SNAPAPI_KEY}` } }
);
if (!ssRes.ok) throw new Error('Screenshot failed');
res.set('Content-Type', 'image/png');
res.set('Cache-Control', 'public, max-age=86400');
res.send(Buffer.from(await ssRes.arrayBuffer()));
} catch (err) {
res.status(500).json({ error: err.message });
}
});
app.listen(3000);
This creates a /preview?url=... endpoint that caches screenshots for 24 hours via Cache-Control headers.
Error Handling Best Practices
Robust error handling is essential for production screenshot integrations:
async function screenshotWithRetry(url, retries = 2) {
for (let i = 0; i <= retries; i++) {
try {
const res = await fetch(
`https://apisnap.dev/api/screenshot?url=${encodeURIComponent(url)}`,
{ headers: { Authorization: `Bearer ${process.env.SNAPAPI_KEY}` } }
);
if (res.status === 429) {
console.warn('Quota exceeded');
return null; // Handle gracefully
}
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return Buffer.from(await res.arrayBuffer());
} catch (err) {
if (i === retries) throw err;
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
}
}
}
Always check for 429 (quota exceeded) separately from other errors. Failed requests (4xx, 5xx) don't count against your quota.