Browsershot Alternative: A Drop-in Replacement for PHP Screenshot Generation
If you're a Laravel/PHP developer maintaining spatie/browsershot, you've felt the pain. 7,000+ GitHub stars. Zero updates since 2021. And every deployment, every new server, every shared hosting environment comes with the same problem: install headless Chrome without permissions.
On shared hosting? Forget it.
On AWS Lambda? You're adding 500MB to your function size just for a screenshot.
On PaaS platforms like Heroku or Platform.sh? System binary dependencies are a nightmare.
There's a simpler way.
The Problem: Why Browsershot Breaks in Production
Browsershot is a PHP wrapper around Puppeteer, which requires a headless Chrome binary. Here's what that means:
Shared Hosting (the most painful scenario):
# Your host doesn't have Chrome installed
# You request root access... denied
# You try to compile from source... permission denied
# You give up and ship a broken feature
Serverless (AWS Lambda, Google Cloud Functions):
# Lambda layer for Chrome = 500MB+
# Increases cold start time significantly
# Costs more due to larger package size
# Still fragile — Chrome crashes in memory-constrained environments
Docker/Containerized:
# Docker image bloats to 1GB+ with Chrome
# CI/CD builds take longer
# Registry storage costs increase
# Memory footprint is heavy
The Browsershot package hasn't been updated since 2021. Security patches are lagging. And the core problem remains: you're managing system-level dependencies in application code.
The Before/After: Code Comparison
Before — Browsershot (with dependency hell):
<?php
use Spatie\Browsershot\Browsershot;
// First, you need to install Chrome on your system (good luck with that)
// $ apt-get install chromium-browser # if you have sudo
// $ brew install chromium # if you're on Mac
// etc...
// THEN you can use it:
Browsershot::url('https://example.com')
->screenshot()
->save($pathToImage);
// Want to add a header? Another dependency.
// Want to wait for JS? Another config.
// Want auth cookies? Another workaround.
// Want to scale? Deploy more servers with Chrome installed.
Problems:
- 500MB+ Chrome binary required on every server
- Installation fails on restricted environments
- No updates since 2021
- Memory-heavy process
- Scaling costs increase with Chrome bloat
After — PageBolt API (zero dependencies):
<?php
use GuzzleHttp\Client;
$client = new Client([
'headers' => ['Authorization' => 'Bearer YOUR_API_KEY']
]);
$response = $client->post('https://api.pagebolt.dev/take_screenshot', [
'json' => ['url' => 'https://example.com']
]);
$data = json_decode($response->getBody(), true);
$imageUrl = $data['imageUrl'];
// Save or stream the image
file_put_contents('screenshot.png', file_get_contents($imageUrl));
Or with pure curl (no dependencies):
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.pagebolt.dev/take_screenshot',
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['url' => 'https://example.com']),
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
echo $data['imageUrl']; // URL to your screenshot
curl_close($ch);
Benefits:
- Zero system dependencies
- Works on any PHP environment (shared hosting, serverless, containers)
- No Chrome installation required
- Fast, lightweight HTTP requests
- Scales instantly without managing infrastructure
Feature Comparison: What Actually Works
| Feature | Browsershot | PageBolt API |
|---|---|---|
| System Dependencies | ❌ Requires headless Chrome binary (500MB+) | ✅ None — HTTP requests only |
| Shared Hosting | ❌ Usually blocked by permissions | ✅ Works everywhere |
| Serverless (Lambda) | ⚠️ Heavy layer (500MB+), slow cold starts | ✅ Lightweight, fast requests |
| Maintenance Status | 🚨 Abandoned (2021) | ✅ Active development |
| CSS/JS Support | ⚠️ Older Chrome engine | ✅ Modern Chromium rendering |
| Authentication | ⚠️ Cookies, workaround-heavy | ✅ Built-in auth support |
| Viewport Control | ✅ Supported | ✅ Full control |
| Custom Headers | ⚠️ Complex setup | ✅ Simple JSON parameter |
| Scaling | ❌ Requires more servers with Chrome | ✅ Scales instantly, no infrastructure |
| Cost (100 screenshots/month) | $50-200 (server overhead) | $1 (pay-per-request) |
Real-World Cost Analysis
Scenario: Generate 5,000 screenshots/month for a SaaS app
Option 1: Self-Hosted Browsershot
- Shared hosting: Can't run it. Upgrade to VPS ($50/month) minimum.
- VPS ($50/month) + Chrome bloat + memory overhead
- System admin time managing dependencies: 3 hrs/month
- Labor cost: $300/month (3 hrs × $100/hr)
- Total: $350/month
Option 2: AWS Lambda with Browsershot Layer
- Lambda layer (500MB Chrome): Increases function size
- Cold starts: 5-10 seconds vs. <100ms with API
- Invocation time overhead
- Layer version management complexity
- Estimated cost: $100/month (storage + compute overhead)
Option 3: PageBolt API
- 5,000 requests × $0.01 = $50/month
- Zero infrastructure management
- Instant scaling
- No system dependencies
- Total: $50/month
Savings with PageBolt: $300/month minimum. Plus 3 hours of engineering time freed.
Migration: Drop-in Replacement in 15 Minutes
Step 1: Create a helper class
<?php
namespace App\Services;
use GuzzleHttp\Client;
class ScreenshotService
{
protected $client;
protected $apiKey;
public function __construct()
{
$this->apiKey = config('services.pagebolt.key');
$this->client = new Client([
'base_uri' => 'https://api.pagebolt.dev',
'headers' => ['Authorization' => "Bearer {$this->apiKey}"]
]);
}
public function takeScreenshot($url, array $options = [])
{
$payload = array_merge(['url' => $url], $options);
$response = $this->client->post('/take_screenshot', ['json' => $payload]);
return json_decode($response->getBody(), true)['imageUrl'];
}
}
Step 2: Replace Browsershot calls
// Before
// Browsershot::url($url)->screenshot()->save($path);
// After
// $url = app(ScreenshotService::class)->takeScreenshot($url);
// file_put_contents($path, file_get_contents($url));
Step 3: Update your .env
PAGEBOLT_API_KEY=your_key_here
That's it. No system binary. No deployment pain. No scaling headaches.
When to Use What
Use PageBolt if:
- You're on shared hosting or serverless
- You generate 100+ screenshots/month
- You want zero infrastructure management
- You need modern CSS/JS rendering
- You value maintainability and reliability
Use Browsershot if:
- You're in a legacy monolith with ancient dependencies
- You have full system admin control and time to manage Chrome
- You generate <10 screenshots/month locally
(Spoiler: PageBolt wins for every real production scenario.)
Next Steps
- Try PageBolt free — 100 requests/month, no credit card. Test with your actual URLs.
- Copy the helper class above — works with Laravel, plain PHP, any framework.
- Migrate one feature — replace one screenshot generation first. Measure the difference.
Your PHP/Laravel app deserves better than a 2021 dependency. Stop fighting Chrome binaries. Start generating screenshots that actually work, everywhere.
PageBolt makes screenshot generation simple, scalable, and dependency-free. Get started free →
Top comments (0)