Node.js SDK
The official Node.js SDK for Capture API provides a modern, TypeScript-ready interface for all capture operations including screenshots, PDFs, content extraction, and animated screenshots.
Installation
# npm
npm install @techulus/capture
# yarn
yarn add @techulus/capture
# pnpm
pnpm add @techulus/capture
Quick Start
import { CaptureClient } from '@techulus/capture';
// Initialize client
const client = new CaptureClient({
apiKey: 'your-api-key',
secret: 'your-api-secret'
});
// Take a screenshot
const screenshot = await client.screenshot('https://example.com');
// Generate PDF
const pdf = await client.pdf('https://example.com');
// Extract content
const content = await client.content('https://example.com');
// Get metadata
const metadata = await client.metadata('https://example.com');
Authentication
Basic Setup
import { CaptureClient } from '@techulus/capture';
const client = new CaptureClient({
apiKey: process.env.CAPTURE_API_KEY,
secret: process.env.CAPTURE_API_SECRET
});
Environment Variables
# .env file
CAPTURE_API_KEY=your-api-key
CAPTURE_API_SECRET=your-api-secret
Custom Configuration
const client = new CaptureClient({
apiKey: 'your-api-key',
secret: 'your-api-secret',
baseUrl: 'https://edge.capture.page', // Use edge endpoint
timeout: 60000, // 60 second timeout
retries: 3 // Retry failed requests 3 times
});
Screenshots
Basic Screenshot
// Simple screenshot
const imageBuffer = await client.screenshot('https://example.com');
// Save to file
import fs from 'fs';
fs.writeFileSync('screenshot.png', imageBuffer);
Advanced Screenshot Options
const screenshot = await client.screenshot('https://example.com', {
// Viewport settings
vw: 1920,
vh: 1080,
scaleFactor: 2,
// Output options
type: 'png',
resizeWidth: 800,
resizeHeight: 600,
// Timing
delay: 3,
waitFor: '.content-loaded',
// Page enhancements
darkMode: true,
blockAds: true,
blockCookieBanners: true,
// Capture area
full: true,
selector: '.main-content',
// Storage
fileName: 'homepage-screenshot',
s3Acl: 'public-read',
s3Redirect: true
});
Device Emulation
// Mobile screenshot
const mobileScreenshot = await client.screenshot('https://example.com', {
emulateDevice: 'iphone_15_pro'
});
// Tablet screenshot
const tabletScreenshot = await client.screenshot('https://example.com', {
emulateDevice: 'ipad_air'
});
// Get available devices
const devices = await client.getDevices();
console.log(devices);
Element-Specific Screenshots
// Capture specific element
const elementScreenshot = await client.screenshot('https://example.com', {
selector: '.hero-section',
transparent: true,
type: 'png'
});
// Capture by ID
const idScreenshot = await client.screenshot('https://example.com', {
selectorId: 'main-content'
});
PDF Generation
Basic PDF
const pdfBuffer = await client.pdf('https://example.com');
// Save to file
import fs from 'fs';
fs.writeFileSync('document.pdf', pdfBuffer);
PDF with Custom Options
const pdf = await client.pdf('https://example.com', {
// Paper settings
format: 'A4',
landscape: false,
// Margins (all required together)
marginTop: '1in',
marginRight: '1in',
marginBottom: '1in',
marginLeft: '1in',
// Rendering
scale: 0.8,
printBackground: true,
// Timing
delay: 2,
// Storage
fileName: 'report-2024',
s3Acl: 'private'
});
Custom Paper Size
const customPdf = await client.pdf('https://example.com', {
width: '8.5in',
height: '11in',
marginTop: '0.5in',
marginRight: '0.5in',
marginBottom: '0.5in',
marginLeft: '0.5in',
printBackground: true
});
Content Extraction
HTML Content
const content = await client.content('https://example.com');
console.log(content.html); // Full HTML
console.log(content.textContent); // Text only
console.log(content.success); // Boolean status
Content with Options
const content = await client.content('https://example.com', {
delay: 3,
waitFor: '.article-content',
userAgent: 'CustomBot/1.0'
});
// Process the content
const cleanText = content.textContent
.replace(/\s+/g, ' ')
.trim();
Metadata Extraction
Basic Metadata
const metadata = await client.metadata('https://example.com');
console.log(metadata.title);
console.log(metadata.description);
console.log(metadata.image);
console.log(metadata.author);
console.log(metadata.lang);
Social Media Tags
const metadata = await client.metadata('https://blog.example.com/post');
// Open Graph data
console.log(metadata.metadata.title);
console.log(metadata.metadata.description);
console.log(metadata.metadata.image);
// Twitter Card data
console.log(metadata.metadata.publisher);
console.log(metadata.metadata.url);
Animated Screenshots
Basic Animation
const animation = await client.animated('https://example.com', {
format: 'mp4',
duration: 10,
fps: 30
});
// Save animation
import fs from 'fs';
fs.writeFileSync('animation.mp4', animation);
Scrolling Animation
const scrollAnimation = await client.animated('https://example.com', {
format: 'gif',
duration: 15,
fps: 24,
scrolling: true,
scrollSpeed: 300,
hideScrollbars: true
});
Mobile Animation
const mobileAnimation = await client.animated('https://example.com', {
emulateDevice: 'iphone_15_pro',
format: 'mp4',
duration: 12,
fps: 30,
darkMode: true
});
Batch Operations
Parallel Screenshots
const urls = [
'https://example.com',
'https://example.com/about',
'https://example.com/contact'
];
const screenshots = await Promise.all(
urls.map(url => client.screenshot(url, {
vw: 1200,
vh: 800,
fileName: `screenshot-${url.split('/').pop()}`,
s3Acl: 'public-read'
}))
);
Sequential Processing with Delay
async function processUrls(urls) {
const results = [];
for (const url of urls) {
const screenshot = await client.screenshot(url);
results.push(screenshot);
// Avoid rate limiting
await new Promise(resolve => setTimeout(resolve, 1000));
}
return results;
}
Error Handling
Basic Error Handling
try {
const screenshot = await client.screenshot('https://example.com');
console.log('Screenshot captured successfully');
} catch (error) {
console.error('Screenshot failed:', error.message);
console.error('Status:', error.status);
console.error('Details:', error.details);
}
Retry Logic
async function captureWithRetry(url, options, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await client.screenshot(url, options);
} catch (error) {
if (attempt === maxRetries) throw error;
console.log(`Attempt ${attempt} failed, retrying...`);
await new Promise(resolve =>
setTimeout(resolve, attempt * 1000)
);
}
}
}
Error Types
try {
const result = await client.screenshot('https://invalid-url');
} catch (error) {
switch (error.status) {
case 400:
console.error('Invalid request parameters');
break;
case 401:
console.error('Authentication failed');
break;
case 403:
console.error('Insufficient credits');
break;
case 429:
console.error('Rate limit exceeded');
break;
case 500:
console.error('Server error');
break;
default:
console.error('Unknown error:', error.message);
}
}
TypeScript Support
Type Definitions
import {
CaptureClient,
ScreenshotOptions,
PDFOptions,
ContentResponse,
MetadataResponse
} from '@techulus/capture';
const client = new CaptureClient({
apiKey: process.env.CAPTURE_API_KEY!,
secret: process.env.CAPTURE_API_SECRET!
});
// Typed options
const options: ScreenshotOptions = {
vw: 1920,
vh: 1080,
type: 'png',
darkMode: true
};
const screenshot: Buffer = await client.screenshot('https://example.com', options);
Interface Examples
interface ScreenshotOptions {
vw?: number;
vh?: number;
scaleFactor?: number;
type?: 'png' | 'jpeg' | 'webp';
delay?: number;
waitFor?: string;
darkMode?: boolean;
blockAds?: boolean;
// ... more options
}
interface PDFOptions {
format?: 'A4' | 'Letter' | 'Legal' | 'A3' | 'A5';
landscape?: boolean;
scale?: number;
printBackground?: boolean;
// ... more options
}
Integration Examples
Express.js API
import express from 'express';
import { CaptureClient } from '@techulus/capture';
const app = express();
const client = new CaptureClient({
apiKey: process.env.CAPTURE_API_KEY,
secret: process.env.CAPTURE_API_SECRET
});
app.get('/screenshot', async (req, res) => {
try {
const { url, width = 1200, height = 800 } = req.query;
const screenshot = await client.screenshot(url, {
vw: parseInt(width),
vh: parseInt(height),
type: 'png'
});
res.set('Content-Type', 'image/png');
res.send(screenshot);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);
Next.js API Route
// pages/api/capture.js
import { CaptureClient } from '@techulus/capture';
const client = new CaptureClient({
apiKey: process.env.CAPTURE_API_KEY,
secret: process.env.CAPTURE_API_SECRET
});
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method not allowed' });
}
try {
const { url, type = 'screenshot' } = req.body;
let result;
switch (type) {
case 'screenshot':
result = await client.screenshot(url);
res.setHeader('Content-Type', 'image/png');
break;
case 'pdf':
result = await client.pdf(url);
res.setHeader('Content-Type', 'application/pdf');
break;
default:
return res.status(400).json({ error: 'Invalid type' });
}
res.send(result);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
Serverless Function (Vercel)
// api/capture.js
import { CaptureClient } from '@techulus/capture';
const client = new CaptureClient({
apiKey: process.env.CAPTURE_API_KEY,
secret: process.env.CAPTURE_API_SECRET
});
export default async function handler(request, response) {
const { url } = request.query;
try {
const screenshot = await client.screenshot(url, {
vw: 1200,
vh: 800,
blockAds: true,
blockCookieBanners: true
});
response.setHeader('Content-Type', 'image/png');
response.setHeader('Cache-Control', 's-maxage=3600');
response.send(screenshot);
} catch (error) {
response.status(500).json({ error: error.message });
}
}
Performance Optimization
Connection Pooling
// Reuse client instance
const client = new CaptureClient({
apiKey: process.env.CAPTURE_API_KEY,
secret: process.env.CAPTURE_API_SECRET,
keepAlive: true, // Reuse connections
maxSockets: 10 // Connection pool size
});
Caching Results
const cache = new Map();
async function getCachedScreenshot(url, options) {
const cacheKey = `${url}-${JSON.stringify(options)}`;
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
const screenshot = await client.screenshot(url, options);
cache.set(cacheKey, screenshot);
// Cache for 1 hour
setTimeout(() => cache.delete(cacheKey), 3600000);
return screenshot;
}
Stream Processing
import { pipeline } from 'stream/promises';
import { createWriteStream } from 'fs';
async function saveScreenshotStream(url, filename) {
const screenshot = await client.screenshot(url);
const writeStream = createWriteStream(filename);
await pipeline(
Readable.from(screenshot),
writeStream
);
}