The 3-line version
Native fetch (Node.js 18+). Replace YOUR_API_KEY with your key from the signup form.
const res = await fetch('https://api.aisnapapi.com/v1/screenshot?url=https://example.com',
{ headers: { Authorization: 'Bearer YOUR_API_KEY' } });
const buf = Buffer.from(await res.arrayBuffer());
await require('fs').promises.writeFile('shot.png', buf);
That's it. The response body is raw PNG bytes — no JSON wrapping, no base64.
Express route returning a screenshot
A simple Express handler that proxies a screenshot of any user-supplied URL:
import express from 'express';
const app = express();
app.get('/screenshot', async (req, res) => {
const url = req.query.url;
const r = await fetch(
`https://api.aisnapapi.com/v1/screenshot?url=${encodeURIComponent(url)}&full_page=true`,
{ headers: { Authorization: `Bearer ${process.env.SNAPAPI_KEY}` } }
);
res.type('image/png');
r.body.pipe(res);
});
app.listen(3000);
Next.js App Router: dynamic OG images
Generate a screenshot-based Open Graph image for any blog post on demand. Put this in app/api/og/route.ts:
export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const slug = searchParams.get('slug');
const target = `https://yourdomain.com/og-preview/${slug}`;
const r = await fetch(
`https://api.aisnapapi.com/v1/screenshot?url=${encodeURIComponent(target)}&width=1200&height=630`,
{ headers: { Authorization: `Bearer ${process.env.SNAPAPI_KEY!}` } }
);
return new Response(r.body, {
headers: {
'Content-Type': 'image/png',
'Cache-Control': 'public, max-age=86400, s-maxage=86400'
}
});
}
Tip: aggressive caching at the CDN means you spend one screenshot per unique OG image, not per pageview.
Cloudflare Workers / Edge
The same code works at the edge — no Node-specific modules, just fetch and the global Response:
export default {
async fetch(req, env) {
const url = new URL(req.url).searchParams.get('url');
const r = await fetch(
`https://api.aisnapapi.com/v1/screenshot?url=${encodeURIComponent(url)}`,
{ headers: { Authorization: `Bearer ${env.SNAPAPI_KEY}` } }
);
return new Response(r.body, { headers: { 'Content-Type': 'image/png' } });
}
};
Save a PDF from a URL
const r = await fetch(
'https://api.aisnapapi.com/v1/screenshot?url=https://en.wikipedia.org/wiki/Web_API&format=pdf',
{ headers: { Authorization: 'Bearer YOUR_API_KEY' } }
);
await require('fs').promises.writeFile('page.pdf', Buffer.from(await r.arrayBuffer()));
Common gotchas
- URL-encode user-supplied URLs. Always wrap in
encodeURIComponent() before interpolating.
- Single-page apps: if you screenshot a React/Vue/SPA and get a blank result, add
&delay=1500 to wait 1.5 seconds before capture.
- Hide cookie banners: pass a
css parameter with .cookie-banner{display:none} to clean up the shot.
- Stream, don't buffer: in HTTP handlers, pipe
r.body directly to your response instead of loading the whole image into memory.
- Cache aggressively: screenshots of static pages don't change every minute. Set
Cache-Control headers downstream and you'll burn fewer of your monthly quota.