Complete Migration Guide: Puppeteer to SnapAPI
Replace 200+ lines of Puppeteer boilerplate with a single API call. This guide covers every common Puppeteer operation with side-by-side code comparisons, a migration checklist, and a real cost analysis.
1. Why Migrate Away from Puppeteer?
Puppeteer is powerful, but running it in production comes with significant operational overhead:
The hidden costs of self-hosted Puppeteer:
- Chrome/Chromium memory leaks โ requires periodic restarts and monitoring
- Browser crashes on complex pages โ needs retry logic and error handling
- Scaling headless browsers is hard โ each instance uses 200-500MB RAM
- Keeping Chrome up to date for security patches
- Handling timeouts, zombie processes, and disk space for temp files
- No built-in ad blocking, cookie banner removal, or device emulation presets
2. Side-by-Side Code Comparisons
Every common Puppeteer operation translated to SnapAPI. Notice the difference in complexity.
Basic Screenshot
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({ headless: 'new', args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage' ] }); const page = await browser.newPage(); await page.setViewport({ width: 1280, height: 800 }); await page.goto('https://example.com', { waitUntil: 'networkidle0' }); await page.screenshot({ path: 'screenshot.png' }); await browser.close(); })();
const res = await fetch( 'https://api.snapapi.pics/v1/screenshot', { method: 'POST', headers: { 'x-api-key': 'YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ url: 'https://example.com' }) } ); fs.writeFileSync( 'screenshot.png', Buffer.from(await res.arrayBuffer()) );
Full-Page Screenshot with Dark Mode
const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox'] }); const page = await browser.newPage(); await page.setViewport({ width: 1280, height: 800 }); // Force dark mode await page.emulateMediaFeatures([ { name: 'prefers-color-scheme', value: 'dark' } ]); await page.goto('https://example.com', { waitUntil: 'networkidle0', timeout: 30000 }); await page.screenshot({ path: 'full.png', fullPage: true }); await browser.close();
const res = await fetch( 'https://api.snapapi.pics/v1/screenshot', { method: 'POST', headers: { 'x-api-key': 'YOUR_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ url: 'https://example.com', fullPage: true, darkMode: true }) } ); // That's it. No browser management, // no Chrome flags, no cleanup.
Mobile Device Emulation
const iPhone = puppeteer.KnownDevices[ 'iPhone 15 Pro' ]; // Hope this device exists... // Puppeteer's list is often outdated const page = await browser.newPage(); await page.emulate(iPhone); await page.goto('https://example.com'); await page.screenshot({ path: 'mobile.png' }); await browser.close();
// 25 real devices always up to date { "url": "https://example.com", "device": "iphone-15-pro" } // Also: iphone-15-pro-max, ipad-pro-11, // pixel-8-pro, samsung-galaxy-s24, // macbook-pro-16, and more.
PDF Generation
const page = await browser.newPage(); await page.goto('https://example.com', { waitUntil: 'networkidle0' }); await page.pdf({ path: 'output.pdf', format: 'A4', printBackground: true, margin: { top: '1cm', bottom: '1cm', left: '1cm', right: '1cm' } }); await browser.close();
{
"url": "https://example.com",
"pdfOptions": {
"pageSize": "a4",
"printBackground": true,
"marginTop": "1cm",
"marginBottom": "1cm"
}
}
// POST to /v1/pdf
// Returns PDF binary directly
Element Screenshot with Wait
const page = await browser.newPage(); await page.goto('https://example.com'); await page.waitForSelector( '#chart-container', { timeout: 10000 } ); // Extra delay for animations await new Promise( r => setTimeout(r, 2000) ); const el = await page.$( '#chart-container' ); await el.screenshot({ path: 'chart.png' }); await browser.close();
{
"url": "https://example.com",
"selector": "#chart-container",
"waitForSelector": "#chart-container",
"delay": 2000
}
// All in a single parameter.
// No browser lifecycle management.
Blocking Ads & Cookie Banners
const puppeteer = require( 'puppeteer-extra' ); const AdblockerPlugin = require( 'puppeteer-extra-plugin-adblocker' ); puppeteer.use(AdblockerPlugin({ blockTrackers: true })); // Cookie banners? You're on your own. // Write custom CSS or JS to hide them. // Or use yet another plugin. const browser = await puppeteer.launch(); // ...
{
"url": "https://example.com",
"blockAds": true,
"blockTrackers": true,
"blockCookieBanners": true,
"blockChatWidgets": true
}
// Built-in. No plugins needed.
// Always up to date filter lists.
Batch Processing
const urls = [/* 100 URLs */]; const CONCURRENCY = 5; async function processUrl(url, browser) { const page = await browser.newPage(); try { await page.goto(url, { timeout: 30000 }); await page.screenshot({/*...*/}); } catch (e) { console.error(url, e); } finally { await page.close(); } } // Build your own queue, concurrency // limiter, retry logic, error handling // ... 50+ more lines
{
"urls": [
"https://example.com",
"https://google.com",
// ... up to 100 URLs
],
"format": "png",
"webhookUrl": "https://you.com/done"
}
// POST to /v1/screenshot/batch
// We handle concurrency, retries,
// and notify you when done.
3. Performance Comparison
| Metric | Puppeteer (self-hosted) | SnapAPI |
|---|---|---|
| Cold start time | 2-5s (browser launch) | 0ms (always warm) |
| Avg screenshot time | 3-5s | 1-2s |
| Memory per instance | 200-500MB | 0MB (API call) |
| Max concurrent | 5-10 per server | Unlimited (rate limited) |
| Reliability | 95-98% (crashes) | 99.9% SLA |
| Chrome updates | Manual | Automatic |
SnapAPI keeps browser pools warm 24/7. Your first request is as fast as your 1000th โ no cold starts, no browser launch overhead.
4. Cost Comparison
Let's compare the real cost of running Puppeteer yourself vs. using SnapAPI for 50,000 screenshots/month:
| Cost Item | Self-Hosted Puppeteer | SnapAPI |
|---|---|---|
| Server (4 CPU, 8GB RAM) | $40-80/mo | โ |
| DevOps / Monitoring | $200-500/mo (time cost) | โ |
| Error handling / retries | $100-200/mo (dev time) | โ |
| Chrome license / updates | Free but time-consuming | โ |
| SnapAPI subscription | โ | $19/mo (Starter) |
| Total | $340-780/mo | $19/mo |
Developer time is the biggest cost. Debugging Puppeteer memory leaks at 3 AM, handling Chrome version mismatches, and building retry logic costs far more than the server itself.
5. Migration Checklist
๐ Step-by-Step Migration
puppeteer.launch() and browser.close(). Replace with HTTP fetch calls.page.setViewport() to width/height params, or use device presets.url field. waitUntil maps directly.fullPage, format, quality map 1:1 to SnapAPI params./v1/pdf endpoint. PDF options map directly.javascript parameter to inject custom JS before capture.waitForSelector parameter. Same CSS selectors work.npm uninstall puppeteer puppeteer-extra puppeteer-extra-plugin-adblockerX-RateLimit-Remaining header.6. Advanced Scenarios
Custom JavaScript Injection
If you use page.evaluate() to modify the page before capturing, use the javascript parameter:
{
"url": "https://example.com",
"javascript": "document.querySelector('.banner').remove(); document.body.style.background = '#fff';",
"delay": 500
}
Authentication / Cookies
If your Puppeteer code sets cookies for authenticated sessions:
{
"url": "https://app.example.com/dashboard",
"cookies": [
{ "name": "session", "value": "abc123", "domain": "app.example.com" }
],
"extraHeaders": {
"Authorization": "Bearer your-token"
}
}
Proxy & Geolocation
{
"url": "https://example.com",
"proxy": { "server": "http://proxy.example.com:8080" },
"geolocation": { "latitude": 40.7128, "longitude": -74.0060 },
"timezone": "America/New_York",
"locale": "en-US"
}
7. FAQ
Can I still use Puppeteer for some things?
Absolutely. SnapAPI covers screenshots, PDFs, videos, and content extraction. If you need complex multi-step browser automation (filling forms, clicking through flows), Puppeteer or Playwright may still be the right tool. Many teams use SnapAPI for capture tasks and keep a small Puppeteer setup for automation.
What about Playwright?
Everything in this guide applies to Playwright too. The API call is identical โ just replace your Playwright code the same way. See our Playwright vs Puppeteer comparison.
Is there a Node.js SDK?
Yes! We have SDKs for JavaScript, Python, Go, PHP, Kotlin, and Swift. Check the documentation for installation instructions. But even without an SDK, it's just a fetch call โ no SDK required.
What if I need more than 50,000 screenshots/month?
Our Business plan supports up to 500,000/month, and we offer custom Enterprise plans for higher volumes. Contact us for details.
Ready to Ditch Puppeteer?
Start with 200 free screenshots. No credit card required. Most teams migrate in under an hour.
Start Free โ snapapi.pics