DEV Community

Custodia-Admin
Custodia-Admin

Posted on

Headless Browser API: Stop Managing Puppeteer. Start Shipping Features.

Headless Browser API: Stop Managing Puppeteer. Start Shipping Features.

Every team that ships browser automation eventually owns Puppeteer. You inherit:

  • 300MB+ Docker images per instance
  • Chrome process management, zombie process cleanup
  • Memory leaks after 1000 page loads
  • $100–500/month infrastructure to run 3–5 concurrent browsers
  • Version conflicts between Puppeteer and your Node version
  • Chromium version mismatches between dev, staging, production

By the time you realize "this is now my job," you've spent 2 months on DevOps instead of features.

PageBolt's headless browser API removes the entire stack. One endpoint, one API key.

The DIY Headless Browser Problem

Puppeteer self-hosted (your server):

const puppeteer = require('puppeteer');

// Every 1000 screenshots, Chrome leaks memory
let browser = await puppeteer.launch({
  headless: true,
  args: ['--disable-dev-shm-usage', '--no-sandbox']
});

for (let i = 0; i < 10000; i++) {
  const page = await browser.newPage();
  await page.setViewport({ width: 1280, height: 720 });
  await page.goto(urls[i], { waitUntil: 'networkidle2' });
  await page.screenshot({ path: `screenshot-${i}.png` });
  await page.close();

  // Restart browser every 1000 pages to clear memory
  if (i % 1000 === 0) {
    await browser.close();
    browser = await puppeteer.launch({ headless: true });
  }
}

await browser.close();
Enter fullscreen mode Exit fullscreen mode

Costs:

  • 300MB base Chrome image
  • 5–10 second startup per fresh browser
  • 1 concurrent browser = ~500MB RAM
  • 10,000 screenshots = ~3–4 hours
  • Infrastructure: EC2 instance (~$50/month) + dev/staging instances

Playwright self-hosted (same problems, different syntax):

const { chromium } = require('playwright');

const browser = await chromium.launch();
// Same memory leak issues
// Same startup overhead
// Same infrastructure costs
Enter fullscreen mode Exit fullscreen mode

The API Solution

PageBolt's headless browser API:

const response = await fetch('https://api.pagebolt.dev/v1/screenshot', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${apiKey}` },
  body: JSON.stringify({
    url: 'https://example.com',
    options: {
      width: 1280,
      height: 720,
      fullPage: true,
      blockAds: true
    }
  })
});

const { image_url } = await response.json();
Enter fullscreen mode Exit fullscreen mode

Same result. 3 lines instead of 50. Zero infrastructure.

Real-World Use Cases

1. Batch Screenshot Processing (10,000 pages)

// Self-hosted: 3–4 hours, $50+/month infrastructure
// PageBolt: 15 minutes, $0 infrastructure

const urls = generateUrls(10000);
const batchSize = 100;

for (let i = 0; i < urls.length; i += batchSize) {
  const batch = urls.slice(i, i + batchSize);

  const promises = batch.map(url =>
    fetch('https://api.pagebolt.dev/v1/screenshot', {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${apiKey}` },
      body: JSON.stringify({ url })
    })
  );

  const results = await Promise.all(promises);

  // Upload all to S3
  for (const res of results) {
    const { image_url } = await res.json();
    await uploadToS3(image_url);
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Multi-Step PDF Generation

// Generate PDF from rendered product page
const sequenceRes = await fetch(
  'https://api.pagebolt.dev/v1/run_sequence',
  {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${apiKey}` },
    body: JSON.stringify({
      steps: [
        { action: 'navigate', url: 'https://shop.example.com/product/123' },
        { action: 'wait', ms: 2000 },  // Wait for JS to render price
        { action: 'click', selector: '.generate-quote' },
        { action: 'pdf', name: 'quote.pdf' }
      ]
    })
  }
);

const { pdf_url } = await sequenceRes.json();
Enter fullscreen mode Exit fullscreen mode

3. Dynamic Screenshot Service (Express.js)

app.get('/api/preview/:id', async (req, res) => {
  const res = await fetch('https://api.pagebolt.dev/v1/screenshot', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.PAGEBOLT_KEY}` },
    body: JSON.stringify({
      url: `https://app.example.com/designs/${req.params.id}`,
      options: { width: 1200, height: 630 }
    })
  });

  const { image_url } = await res.json();
  res.json({ preview_url: image_url });
});
Enter fullscreen mode Exit fullscreen mode

Cost Comparison

Task Puppeteer Self-Hosted PageBolt API
100 screenshots/day $50–100/mo (instance) + 4 hours dev time $29/mo (incl. 10,000/mo quota)
1,000 screenshots/day $200–300/mo (dedicated box) + DevOps $99/mo (100,000/mo quota)
10,000 screenshots/day $500+/mo (fleet) + on-call ops $299/mo (unlimited)
Memory per concurrent 300MB per browser <1KB per request
Startup time 5–10 seconds (fresh Chrome) <1 second (API call)

Break-even: 1,000 screenshots/month. Beyond that, PageBolt is 10x cheaper.

Why Headless Browser API > Self-Hosted

  1. You don't own infrastructure — No crash pages, no restarts, no on-call rotation
  2. Automatic scaling — 10 screenshots or 10,000; same API call
  3. Browser updates included — Chrome patches, new features, security fixes — automatic
  4. Handles edge cases — Ad-blocking, cookie banners, geolocation, proxy chains — all built-in
  5. Cost transparency — Pay per use, not per instance

Pricing

  • Free: 100 screenshots + PDFs/month
  • Starter: $29/month → 10,000/month
  • Scale: $99/month → 100,000/month

Next Steps

  1. Get free API key: pagebolt.dev/pricing
  2. Run first screenshot: curl https://api.pagebolt.dev/v1/screenshot ...
  3. Read docs: pagebolt.dev/docs

Try free — 100 requests/month, no credit card.

Top comments (0)