Screenshot API for Node.js: Replace Puppeteer in 2 Lines of Code
You're building a Node.js application that needs screenshots. Invoices. Reports. Social cards. Website monitoring.
Your instinct: Puppeteer. It works, but it's heavy.
Puppeteer is a browser automation library. Screenshots are just a side effect. You're installing 150MB+ of Chromium, managing processes, debugging crashes, handling timeouts—all for something that should be simple.
There's a better way for Node.js developers.
The Puppeteer Problem in Node.js
Here's what screenshot generation looks like with Puppeteer in a Node.js app:
const puppeteer = require('puppeteer');
async function takeScreenshot(url) {
// Launch browser (includes Chromium download on first run)
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 720 });
try {
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
const screenshot = await page.screenshot({ encoding: 'binary' });
return screenshot;
} finally {
await browser.close();
}
}
// Usage
const imageBuffer = await takeScreenshot('https://example.com');
fs.writeFileSync('screenshot.png', imageBuffer);
That's 18 lines for one screenshot. And that doesn't include:
- Error handling for timeouts
- Memory leak prevention
- Cookie/auth management
- Scaling to multiple concurrent screenshots
- Browser version management
The PageBolt Alternative
Here's the same task with PageBolt's screenshot API:
const response = await fetch('https://api.pagebolt.dev/v1/screenshot', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: JSON.stringify({ url: 'https://example.com' })
});
const { image_url } = await response.json();
console.log('Screenshot ready:', image_url);
That's 2 lines. No browser. No process management. No maintenance.
Node.js Development: Why This Matters
Node.js developers often run screenshot generation in production. Common patterns:
Express.js server generating reports:
app.post('/generate-report', async (req, res) => {
// Puppeteer approach: Launch browser per request
// Memory: 300MB per browser instance
// Startup: 5-10 seconds per request
// If 10 concurrent users: 3GB memory, potential crashes
// PageBolt approach: HTTP request
// Memory: ~1KB per request
// Startup: <1 second
// Scales to 1000s of concurrent requests
});
Webhook handler (e.g., Stripe, GitHub):
// Webhooks fire unpredictably
// Puppeteer: Can't pre-allocate browser pool
// Server crashes if multiple webhooks fire simultaneously
// PageBolt: Just make an API call
// Scales automatically
Scheduled job (e.g., daily reporting):
// Puppeteer: Need dedicated server with 2GB+ RAM
// Cost: $30-60/month minimum
// PageBolt: API call from any server
// Cost: $9/month
Comparison: Puppeteer vs PageBolt in Node.js
| Aspect | Puppeteer | PageBolt |
|---|---|---|
| Code lines | 18+ | 2 |
| Memory per screenshot | 300MB+ | <1KB |
| Startup time | 5-10 seconds | <1 second |
| Max concurrent | 2-3 per 1GB RAM | Unlimited (API-backed) |
| Browser install | 150MB Chromium | None |
| Maintenance | Update Chromium, manage processes | None |
| Server needed | t3.medium ($28/mo) | Any server, any size |
| Scaling cost | Add servers ($28/mo each) | Fixed API cost |
Real-World Node.js Scenarios
Scenario 1: Express.js Report Generation
Generate PDF reports with screenshots for users:
app.post('/reports/:id', async (req, res) => {
const reportId = req.params.id;
// Take screenshot of report preview
const screenshotRes = await fetch('https://api.pagebolt.dev/v1/screenshot', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.PAGEBOLT_KEY}` },
body: JSON.stringify({ url: `https://myapp.com/preview/${reportId}` })
});
const { image_url } = await screenshotRes.json();
// Generate PDF with screenshot
const pdf = await generatePdf({
title: `Report ${reportId}`,
screenshot: image_url
});
res.setHeader('Content-Type', 'application/pdf');
res.send(pdf);
});
With Puppeteer:
- Each request: Launch browser (10 sec) + take screenshot + close browser
- Memory: 300MB per concurrent request
- Server crashes at 10+ concurrent users
- Cost: t3.large ($56/mo)
With PageBolt:
- Each request: API call (1 sec)
- Memory: <1KB per request
- Scales to 1000s of concurrent users
- Cost: $29/mo
Scenario 2: Daily Monitoring Screenshots
Monitor competitors' websites daily, store screenshots in S3:
// src/jobs/monitor-competitors.js
const schedule = require('node-schedule');
schedule.scheduleJob('0 9 * * *', async () => {
const competitors = [
'https://competitor1.com',
'https://competitor2.com',
'https://competitor3.com'
];
for (const url of competitors) {
const res = await fetch('https://api.pagebolt.dev/v1/screenshot', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.PAGEBOLT_KEY}` },
body: JSON.stringify({ url })
});
const { image_url } = await res.json();
// Store in S3
await s3.putObject({
Bucket: 'monitoring',
Key: `${new URL(url).hostname}/${new Date().toISOString()}.png`,
Body: await fetch(image_url).then(r => r.buffer())
});
}
});
Cost comparison:
- Puppeteer: Needs always-on EC2 instance ($28/mo) + storage
- PageBolt: 3 screenshots/day = $0.09/month + storage
Scenario 3: Webhook Handler (Stripe/GitHub)
Generate screenshot when webhook fires:
app.post('/webhook/stripe', async (req, res) => {
const event = req.body;
if (event.type === 'charge.succeeded') {
const invoiceUrl = `https://myapp.com/invoices/${event.data.object.id}`;
// Take screenshot immediately
const screenshotRes = await fetch('https://api.pagebolt.dev/v1/screenshot', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.PAGEBOLT_KEY}` },
body: JSON.stringify({ url: invoiceUrl, format: 'png' })
});
const { image_url } = await screenshotRes.json();
// Store in database for audit trail
await db.insert('invoice_screenshots', {
charge_id: event.data.object.id,
screenshot_url: image_url,
timestamp: new Date()
});
}
res.json({ received: true });
});
Advantages over Puppeteer:
- No "screenshot pool" needed
- No memory management
- Handles traffic spikes automatically
- Webhook handler stays lightweight
Pricing for Node.js Developers
| Volume | Monthly Cost | Cost Per Screenshot |
|---|---|---|
| 100 screenshots | $0 (Free tier) | Free |
| 500 screenshots | $9 (Hobby) | $0.018 |
| 5,000 screenshots | $29 (Starter) | $0.006 |
| 50,000 screenshots | $99 (Pro) | $0.002 |
At 1,000 screenshots/month:
- Puppeteer + server: $28-60/mo
- PageBolt: $29/mo
- Break-even first month
Integrations for Node.js Developers
With Express.js
const pagebolt = require('@pagebolt/express');
app.use(pagebolt({ apiKey: process.env.PAGEBOLT_KEY }));
app.post('/screenshot', async (req, res) => {
const screenshot = await res.locals.pagebolt.screenshot(req.body.url);
res.json(screenshot);
});
With NestJS
import { PageBoltService } from '@pagebolt/nestjs';
@Controller('screenshots')
export class ScreenshotController {
constructor(private pagebolt: PageBoltService) {}
@Post()
async create(@Body() { url }: CreateScreenshotDto) {
return this.pagebolt.screenshot(url);
}
}
With Serverless (AWS Lambda, Vercel)
// Lambda handler
export const handler = async (event) => {
const res = await fetch('https://api.pagebolt.dev/v1/screenshot', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.PAGEBOLT_KEY}` },
body: JSON.stringify({ url: event.queryStringParameters.url })
});
return {
statusCode: 200,
body: JSON.stringify(await res.json())
};
};
Lambda + Puppeteer: Requires 512MB memory layer, cold starts 15-30 sec, timeouts common.
Lambda + PageBolt: 128MB memory fine, <1 second execution, 99.9% uptime.
Getting Started
- Sign up at pagebolt.dev/pricing
- Get API key (60 seconds)
- Add to your Node.js app (2 lines)
- Deploy with confidence
Free tier: 100 screenshots/month. Paid: $9-99/month depending on volume.
For Node.js developers, PageBolt removes the infrastructure burden. Focus on your app, not browser management.
Start generating screenshots: pagebolt.dev/pricing — 100 free, then $9/month for 500.
Top comments (0)