Screenshot API for Node.js: fetch, axios & Serverless Integration
Capture screenshots, scrape web pages, and generate PDFs from Node.js using the native fetch API or axios. Works with Express, Fastify, NestJS, and serverless platforms — no Puppeteer or browser binaries required.
Screenshot API for Node.js — Native fetch Quickstart
Node.js 18 and later includes the native Fetch API, eliminating the need for axios or node-fetch for basic HTTP calls. Here is a complete screenshot function using only built-in Node.js APIs:
const { writeFile } = require('fs/promises');
async function captureScreenshot(url, apiKey) {
const params = new URLSearchParams({
url,
full_page: 'true',
format: 'jpeg',
block_ads: 'true',
block_cookies: 'true'
});
const response = await fetch(
`https://api.snapapi.pics/v1/screenshot?${params}`,
{
headers: { 'X-Api-Key': apiKey },
signal: AbortSignal.timeout(30_000)
}
);
if (!response.ok) {
const error = await response.text();
throw new Error(`SnapAPI ${response.status}: ${error}`);
}
return Buffer.from(await response.arrayBuffer());
}
// Usage
const imageBuffer = await captureScreenshot('https://example.com', process.env.SNAPAPI_KEY);
await writeFile('screenshot.jpg', imageBuffer);
console.log(`Saved ${imageBuffer.length} bytes`);
AbortSignal.timeout(30_000) cancels the request after 30 seconds without requiring a manual AbortController. For video recording requests that take longer, increase the timeout to 120 seconds. The arrayBuffer() method returns raw binary data that Buffer.from() converts to a Node.js Buffer for file writing or streaming.
Using axios for Older Node.js Versions
For Node.js 14 and 16, or projects that prefer axios for its interceptor and retry support:
const axios = require('axios');
async function captureScreenshot(url, apiKey) {
const response = await axios.get('https://api.snapapi.pics/v1/screenshot', {
params: { url, full_page: true, format: 'jpeg', block_ads: true },
headers: { 'X-Api-Key': apiKey },
responseType: 'arraybuffer',
timeout: 30000
});
return Buffer.from(response.data);
}
// With axios-retry for automatic backoff on transient failures:
const axiosRetry = require('axios-retry');
axiosRetry(axios, {
retries: 3,
retryDelay: axiosRetry.exponentialDelay,
retryCondition: (error) => error.response?.status === 429 || error.response?.status >= 500
});
Set responseType: 'arraybuffer' to receive the binary image data rather than a string. The axios-retry middleware handles exponential backoff automatically, retrying on 429 rate limit and 5xx server error responses.
Express.js Integration: Screenshot Proxy Endpoint
Build a screenshot proxy in Express that adds your API key server-side and streams the result to the client. This pattern keeps your API key out of the browser while allowing frontend applications to request screenshots:
const express = require('express');
const app = express();
app.get('/screenshot', async (req, res) => {
const { url } = req.query;
if (!url) return res.status(400).json({ error: 'url required' });
try {
const params = new URLSearchParams({ url, full_page: 'true', format: 'jpeg' });
const upstream = await fetch(`https://api.snapapi.pics/v1/screenshot?${params}`, {
headers: { 'X-Api-Key': process.env.SNAPAPI_KEY },
signal: AbortSignal.timeout(30_000)
});
if (!upstream.ok) return res.status(upstream.status).json({ error: 'Capture failed' });
res.set('Content-Type', 'image/jpeg');
res.set('Cache-Control', 'public, max-age=3600');
upstream.body.pipeTo(new WritableStream({
write(chunk) { res.write(chunk); },
close() { res.end(); }
}));
} catch (err) {
res.status(500).json({ error: err.message });
}
});
app.listen(3000);
The response is streamed from SnapAPI directly to the Express response, avoiding buffering the full image in memory. The Cache-Control header tells browsers and CDNs to cache the screenshot for one hour, reducing repeat API calls for the same URL.
NestJS Integration with Injectable Service
In NestJS, wrap SnapAPI in an @Injectable() service and use HttpModule for dependency-injected HTTP calls:
@Injectable()
export class ScreenshotService {
constructor(private readonly httpService: HttpService,
private readonly config: ConfigService) {}
async capture(url: string): Promise<Buffer> {
const params = new URLSearchParams({ url, full_page: 'true', format: 'jpeg' });
const response = await firstValueFrom(
this.httpService.get(`https://api.snapapi.pics/v1/screenshot?${params}`, {
headers: { 'X-Api-Key': this.config.get('SNAPAPI_KEY') },
responseType: 'arraybuffer',
timeout: 30000
})
);
return Buffer.from(response.data);
}
}
Inject ScreenshotService into any controller or other service. The ConfigService reads the API key from your NestJS configuration module, supporting environment-specific values in .env files or cloud secret managers.
Serverless Deployment: AWS Lambda, Vercel & Cloudflare Workers
SnapAPI is ideal for serverless environments because it eliminates the browser binary dependency that makes running Puppeteer on Lambda painful. Your serverless function makes a standard HTTPS request and returns the result — no cold start overhead from launching Chromium, no layer size limits to work around.
// AWS Lambda handler (Node.js 18+ runtime)
exports.handler = async (event) => {
const url = event.queryStringParameters?.url;
if (!url) return { statusCode: 400, body: 'Missing url' };
const params = new URLSearchParams({ url, full_page: 'true', format: 'jpeg' });
const res = await fetch(`https://api.snapapi.pics/v1/screenshot?${params}`, {
headers: { 'X-Api-Key': process.env.SNAPAPI_KEY }
});
const imageData = Buffer.from(await res.arrayBuffer()).toString('base64');
return {
statusCode: 200,
headers: { 'Content-Type': 'image/jpeg' },
body: imageData,
isBase64Encoded: true
};
};
Lambda requires base64-encoded binary responses via API Gateway. The pattern works identically on Vercel Edge Functions and Cloudflare Workers using the standard Fetch API. Store your SnapAPI key in Lambda environment variables, Vercel environment settings, or Cloudflare Worker secrets.
Start for free at snapapi.pics — 200 captures per month, no credit card required. The official Node.js SDK at github.com/Sleywill/snapapi-js wraps all endpoints with full TypeScript support. Install with npm install snapapi-js.