DEV Community

Custodia-Admin
Custodia-Admin

Posted on

Screenshot API for Node.js: Replace Puppeteer in 2 Lines of Code

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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
});
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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())
    });
  }
});
Enter fullscreen mode Exit fullscreen mode

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 });
});
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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())
  };
};
Enter fullscreen mode Exit fullscreen mode

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

  1. Sign up at pagebolt.dev/pricing
  2. Get API key (60 seconds)
  3. Add to your Node.js app (2 lines)
  4. 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)