spatie/browsershot
Convert web pages or HTML to images and PDFs using headless Chrome via Puppeteer. Capture screenshots, generate PDFs, render JS, extract body HTML, and inspect network requests. Simple fluent API for URLs, raw HTML, or local HTML files.
spatie/browsershot excels in converting dynamic HTML (including JS-rendered content) to static formats (PDF, images, or HTML strings). This aligns perfectly with common TPM needs for:
evaluateOnNewDocument, custom headers, timeouts), enabling advanced use cases like:
page.evaluate()).pdf() options).npm install -g puppeteer).file_get_contents for local HTML files.Browsershot::url()->delay(60)->save()) for async rendering.Storage::disk('s3')->put()).browsershot bridges this gap for PHP.| Risk Area | Severity | Mitigation |
|---|---|---|
| Node.js Dependency | High | Containerize Puppeteer (Docker) or use platform-specific installers (e.g., apt-get). |
| Chrome Version Lock | Medium | Pin Puppeteer version in composer.json (e.g., "puppeteer/puppeteer": "^23.0"). |
| Memory/CPU Usage | Medium | Use setNodeOptions(['--no-sandbox']) in Docker and limit Chrome flags (e.g., --disable-gpu). |
| Local File Security | High | Disable file:// URLs via setBlockedRequests(['file://*']) (default in v5+). |
| PDF Text Extraction | Low | Install poppler-utils only if needed for OCR/searchable PDFs. |
| CI/CD Complexity | Medium | Use GitHub Actions with pre-installed Node.js or Docker layers. |
Browsershot::setNodeOptions()).sleep() between jobs to avoid OOM.setBlockedRequests() to block untrusted domains.--no-sandbox disabled in production)?setChromePath() to specify a non-headless Chrome build.poppler-utils is installed.puppeteer-core).spatie/browsershot with a multi-stage build to reduce image size.throwOnRemoteConnectionError() and wrap calls in try-catch.| Component | Integration Strategy | Tools/Libraries |
|---|---|---|
| Laravel | Use as a service provider (BrowsershotServiceProvider) with config binding. |
Laravel’s config(), Storage, Queue. |
| Node.js | Install via npm or Docker (recommended for consistency). | npm install -g puppeteer or FROM node:18. |
| Chrome | Use system Chrome or pre-installed binaries (e.g., puppeteer-core). |
setChromePath() or Docker’s Chrome image. |
| Storage | Save outputs to local disk, S3, or database (e.g., Storage::put()). |
Laravel Filesystem, Spatie Media Library. |
| Queue System | Offload rendering to Laravel Queues (Redis, Database) for async processing. | Browsershot::url()->delay(60)->save(). |
| CI/CD | Use Docker or pre-installed Node.js in GitHub Actions. | actions/setup-node@v4 or custom Docker. |
Browsershot::htmlFromFilePath()) to test rendering.chrome_path, node_options).
$this->app->singleton(Browsershot::class, function ($app) {
return Browsershot::withNodeOptions(['--no-sandbox'])
->setChromePath('/usr/bin/google-chrome');
});
class GeneratePdfJob implements ShouldQueue {
public function handle() {
Browsershot::url($this->url)->save(storage_path('app/pdf.pdf'));
}
}
evaluate() to modify DOM before rendering.
Browsershot::html($html)
->evaluate('document.querySelector(".hidden").style.display = "none"')
->save('output.pdf');
Browsershot calls with Puppeteer’s PDFOptions.
$pdf = Browsershot::html($html1)->pdf();
$pdf->merge(Browsershot::html($html2)->pdf());
--no-sandbox in production.poppler-utils (brew install poppler).setAllowInsecureHttp(true) for Vite/HMR.setExtraChromeFlags(['--disable-web-security']) (dev only).spatie/browsershot to composer.json:
composer require spatie/browsershot
php artisan vendor:publish --provider="Spatie\Browsershot\BrowsershotServiceProvider".How can I help you explore Laravel packages today?