# Laravel PDF
Laravel PDF is a package by Spatie that provides a simple, elegant way to create PDFs in Laravel applications. It supports multiple PDF generation backends through a driver-based architecture: Browsershot (Chromium-based, default), Gotenberg (Docker-based), Cloudflare Browser Rendering API, and DOMPDF (pure PHP). The Chromium-based drivers support modern CSS features like flexbox, grid, and Tailwind CSS, while DOMPDF offers a zero-dependency solution for simpler PDFs.
The package integrates seamlessly with Laravel's Blade templating, filesystem abstraction, and queue system. You can render Blade views as PDFs, save them locally or to cloud storage (S3, etc.), return them as HTTP responses, and generate them in background queues. It also includes a comprehensive testing API with fakes and assertions for verifying PDF generation in your test suite.
## Installation
Install the package via Composer, then optionally install a driver dependency.
```bash
# Install the package
composer require spatie/laravel-pdf
# For Browsershot driver (default) - requires Node.js and Chrome
composer require spatie/browsershot
# For DOMPDF driver (pure PHP, no external dependencies)
composer require dompdf/dompdf
# Publish config file (optional)
php artisan vendor:publish --tag=pdf-config
```
## Creating PDFs from Blade Views
Render a Blade view as a PDF and save it to the filesystem. Pass data to the view as the second argument.
```php
use Spatie\LaravelPdf\Facades\Pdf;
// Basic usage - render view and save
Pdf::view('pdf.invoice')->save('/path/to/invoice.pdf');
// Pass data to the view
Pdf::view('pdf.invoice', ['invoice' => $invoice, 'customer' => $customer])
->save('/path/to/invoice.pdf');
// Create PDF from raw HTML
Pdf::html('
Hello World
This is a PDF document.
')
->save('/path/to/document.pdf');
```
## Returning PDFs as HTTP Responses
Return a PDF directly from a controller as an HTTP response. Use the `pdf()` helper or the Facade.
```php
use Spatie\LaravelPdf\Facades\Pdf;
use function Spatie\LaravelPdf\Support\pdf;
class InvoiceController
{
// Using the helper function - inline display in browser
public function show(Invoice $invoice)
{
return pdf('pdf.invoice', ['invoice' => $invoice])
->name('invoice-2024.pdf');
}
// Force download instead of inline display
public function download(Invoice $invoice)
{
return Pdf::view('pdf.invoice', ['invoice' => $invoice])
->name('invoice-2024.pdf')
->download();
}
}
```
## Page Format and Orientation
Set page size, orientation, and margins using fluent methods. Supports standard formats and custom dimensions.
```php
use Spatie\LaravelPdf\Facades\Pdf;
use Spatie\LaravelPdf\Enums\Format;
use Spatie\LaravelPdf\Enums\Orientation;
use Spatie\LaravelPdf\Enums\Unit;
Pdf::view('pdf.report', ['data' => $data])
->format(Format::A4) // Standard format (A4, Letter, Legal, etc.)
->landscape() // Landscape orientation
->margins(20, 15, 20, 15, Unit::Millimeter) // Top, right, bottom, left margins
->save('report.pdf');
// Custom paper size (e.g., for receipts)
Pdf::view('pdf.receipt', ['order' => $order])
->paperSize(80, 200, 'mm') // Width, height, unit
->orientation(Orientation::Portrait)
->save('receipt.pdf');
```
## Headers and Footers
Add repeating headers and footers to every page. Use Blade views or raw HTML with page number directives.
```php
use Spatie\LaravelPdf\Facades\Pdf;
Pdf::view('pdf.contract', ['contract' => $contract])
->headerView('pdf.header', ['company' => $company])
->footerView('pdf.footer')
->format('a4')
->save('contract.pdf');
// Using raw HTML for header/footer
Pdf::view('pdf.invoice', ['invoice' => $invoice])
->headerHtml('Company Name
')
->footerHtml('Page @pageNumber of @totalPages
')
->save('invoice.pdf');
```
```blade
{{-- resources/views/pdf/footer.blade.php --}}
```
## Saving to Cloud Storage Disks
Save PDFs directly to any Laravel filesystem disk (S3, GCS, etc.) using the `disk()` method.
```php
use Spatie\LaravelPdf\Facades\Pdf;
// Save to S3
Pdf::view('pdf.invoice', ['invoice' => $invoice])
->disk('s3')
->save('invoices/invoice-2024-001.pdf');
// Save with custom visibility
Pdf::view('pdf.report', ['report' => $report])
->disk('s3', 'public')
->save('reports/monthly-report.pdf');
```
## Queued PDF Generation
Generate PDFs in background queues for better performance. Chain callbacks for success/failure handling.
```php
use Spatie\LaravelPdf\Facades\Pdf;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Log;
Pdf::view('pdf.invoice', ['invoice' => $invoice])
->format('a4')
->disk('s3')
->saveQueued('invoices/invoice.pdf')
->onQueue('pdfs')
->onConnection('redis')
->then(function (string $path, ?string $diskName) use ($user) {
// PDF generated successfully - send email notification
Mail::to($user)->send(new InvoiceReady($path, $diskName));
})
->catch(function (Throwable $e) {
Log::error('PDF generation failed: ' . $e->getMessage());
});
```
## PDF Metadata
Set document metadata like title, author, and keywords that appear in PDF viewers.
```php
use Spatie\LaravelPdf\Facades\Pdf;
Pdf::view('pdf.invoice', ['invoice' => $invoice])
->meta(
title: 'Invoice #' . $invoice->number,
author: 'Acme Corporation',
subject: 'Monthly Invoice',
keywords: 'invoice, billing, acme',
creator: 'My Laravel App',
creationDate: now()
)
->save('invoice.pdf');
```
## Advanced Formatting Options
Use scale, page ranges, tagged PDFs, and conditional formatting for advanced output control.
```php
use Spatie\LaravelPdf\Facades\Pdf;
Pdf::view('pdf.report', ['report' => $report])
->format('a4')
->scale(0.75) // Scale content (0.1 to 2.0)
->pageRanges('1-3, 5, 7-10') // Include specific pages only
->tagged() // Generate accessible/tagged PDF
->save('report.pdf');
// Conditional formatting based on data
Pdf::view('pdf.invoice', ['invoice' => $invoice])
->format('a4')
->when($invoice->isLandscape(), fn ($pdf) => $pdf->landscape())
->when($invoice->hasLetterhead(), fn ($pdf) => $pdf->headerView('pdf.letterhead'))
->unless($invoice->isCompact(), fn ($pdf) => $pdf->margins(20, 15, 20, 15))
->save('invoice.pdf');
```
## Multi-Page PDFs with Page Breaks
Use Blade directives to create multi-page documents with explicit page breaks and page numbers.
```blade
{{-- resources/views/pdf/report.blade.php --}}
Executive Summary
{{ $report->summary }}
@pageBreak
Detailed Analysis
@foreach($report->sections as $section)
{{ $section->title }}
{{ $section->content }}
@if(!$loop->last)
@pageBreak
@endif
@endforeach
```
## Driver Selection and Configuration
Switch between PDF drivers globally or per-PDF. Configure via environment variables or at runtime.
```php
use Spatie\LaravelPdf\Facades\Pdf;
// Use a specific driver for this PDF
Pdf::view('pdf.invoice', ['invoice' => $invoice])
->driver('cloudflare') // 'browsershot', 'cloudflare', 'dompdf', 'gotenberg'
->format('a4')
->save('invoice.pdf');
// Environment configuration (.env)
// LARAVEL_PDF_DRIVER=cloudflare
// CLOUDFLARE_API_TOKEN=your-token
// CLOUDFLARE_ACCOUNT_ID=your-account-id
// Or for Gotenberg (Docker-based)
// LARAVEL_PDF_DRIVER=gotenberg
// GOTENBERG_URL=http://localhost:3000
```
## Customizing Browsershot
Customize the underlying Browsershot instance for advanced Chrome/Puppeteer options.
```php
use Spatie\LaravelPdf\Facades\Pdf;
use Spatie\Browsershot\Browsershot;
Pdf::view('pdf.invoice', ['invoice' => $invoice])
->withBrowsershot(function (Browsershot $browsershot) {
$browsershot
->scale(0.8)
->setOption('args', ['--disable-web-security'])
->waitUntilNetworkIdle();
})
->save('invoice.pdf');
// Set Browsershot defaults for all PDFs in a service provider
Pdf::default()->withBrowsershot(function (Browsershot $browsershot) {
$browsershot->setOption('args', [
'--disable-web-security',
'--allow-file-access-from-files',
]);
});
```
## AWS Lambda PDF Generation
Offload PDF generation to AWS Lambda using Sidecar for better performance and scalability.
```php
use Spatie\LaravelPdf\Facades\Pdf;
// Generate single PDF on Lambda
Pdf::view('pdf.invoice', $data)
->onLambda()
->save('invoice.pdf');
// Set Lambda as default for all PDFs (in service provider)
Pdf::default()->onLambda();
```
## Setting Global Defaults
Configure default options for all PDFs in a service provider.
```php
use Spatie\LaravelPdf\Facades\Pdf;
use Spatie\LaravelPdf\Enums\Format;
// In AppServiceProvider::boot()
Pdf::default()
->headerView('pdf.default-header')
->footerView('pdf.default-footer')
->format(Format::A4)
->margins(15, 10, 15, 10);
// Individual PDFs can still override defaults
Pdf::html('Hello
')
->format(Format::Letter) // Overrides A4 default
->save('document.pdf');
```
## Extending with Macros
Add custom methods to the PdfBuilder class using Laravel's macro functionality.
```php
use Spatie\LaravelPdf\PdfBuilder;
// In AppServiceProvider::boot()
PdfBuilder::macro('companyInvoice', function (string $invoiceNumber) {
return $this
->headerView('pdf.company-header')
->footerHtml('Invoice ' . $invoiceNumber . '
')
->format('a4');
});
// Usage
Pdf::view('pdf.invoice', ['invoice' => $invoice])
->companyInvoice($invoice->number)
->save('invoice.pdf');
```
## Creating Custom Drivers
Implement the PdfDriver interface to create custom PDF generation backends.
```php
namespace App\Pdf\Drivers;
use Spatie\LaravelPdf\Drivers\PdfDriver;
use Spatie\LaravelPdf\PdfOptions;
class WeasyPrintDriver implements PdfDriver
{
public function __construct(protected array $config = []) {}
public function generatePdf(
string $html,
?string $headerHtml,
?string $footerHtml,
PdfOptions $options,
): string {
// Generate PDF and return content as string
$process = Process::run(['weasyprint', '-', '-'], $html);
return $process->output();
}
public function savePdf(
string $html,
?string $headerHtml,
?string $footerHtml,
PdfOptions $options,
string $path,
): void {
file_put_contents($path, $this->generatePdf($html, $headerHtml, $footerHtml, $options));
}
}
// Register in service provider
$this->app->singleton('laravel-pdf.driver.weasyprint', fn () => new WeasyPrintDriver());
// Use the custom driver
Pdf::view('invoice')->driver('weasyprint')->save('invoice.pdf');
```
## Testing PDFs
Use the fake() method to mock PDF generation and make assertions in tests.
```php
use Spatie\LaravelPdf\Facades\Pdf;
use Spatie\LaravelPdf\PdfBuilder;
it('generates an invoice PDF', function () {
Pdf::fake();
$invoice = Invoice::factory()->create();
$this->get(route('invoice.download', $invoice))->assertOk();
// Assert PDF was returned as response
Pdf::assertRespondedWithPdf(function (PdfBuilder $pdf) use ($invoice) {
return $pdf->downloadName === 'invoice.pdf'
&& $pdf->isDownload()
&& str_contains($pdf->html, $invoice->number);
});
});
it('saves invoice to storage', function () {
Pdf::fake();
GenerateInvoice::dispatch($invoice);
// Assert PDF was saved to specific path
Pdf::assertSaved(function (PdfBuilder $pdf, string $path) {
return $path === storage_path('invoices/invoice.pdf')
&& $pdf->viewName === 'pdf.invoice';
});
});
it('queues PDF generation', function () {
Pdf::fake();
QueueInvoice::dispatch($invoice);
Pdf::assertQueued(function (PdfBuilder $pdf, string $path) {
return $path === 'invoice.pdf' && $pdf->contains('Total');
});
});
// Simple assertion methods
Pdf::assertViewIs('pdf.invoice');
Pdf::assertSee('Total: $100.00');
Pdf::assertViewHas('invoice', $invoice);
Pdf::assertNotQueued();
```
## Using Tailwind CSS
Style PDFs with Tailwind CSS using the Chromium-based drivers (Browsershot, Cloudflare, Gotenberg).
```blade
{{-- resources/views/pdf/invoice.blade.php --}}
Invoice
#{{ $invoice->number }}
| Item |
Amount |
@foreach($invoice->items as $item)
| {{ $item->name }} |
${{ number_format($item->amount, 2) }} |
@endforeach
Total: ${{ number_format($invoice->total, 2) }}
```
## Inline Images in Headers/Footers
Use the @inlinedImage directive to embed images in headers and footers.
```blade
{{-- resources/views/pdf/header.blade.php --}}
{{-- Or use a URL --}}
@inlinedImage('https://example.com/logo.png')
```
## Configuration Reference
Complete configuration file with all available options.
```php
// config/laravel-pdf.php
return [
'driver' => env('LARAVEL_PDF_DRIVER', 'browsershot'),
'browsershot' => [
'node_binary' => env('LARAVEL_PDF_NODE_BINARY'),
'npm_binary' => env('LARAVEL_PDF_NPM_BINARY'),
'chrome_path' => env('LARAVEL_PDF_CHROME_PATH'),
'node_modules_path' => env('LARAVEL_PDF_NODE_MODULES_PATH'),
'include_path' => env('LARAVEL_PDF_INCLUDE_PATH'),
'bin_path' => env('LARAVEL_PDF_BIN_PATH'),
'temp_path' => env('LARAVEL_PDF_TEMP_PATH'),
'write_options_to_file' => env('LARAVEL_PDF_WRITE_OPTIONS_TO_FILE', false),
'no_sandbox' => env('LARAVEL_PDF_NO_SANDBOX', false),
],
'cloudflare' => [
'api_token' => env('CLOUDFLARE_API_TOKEN'),
'account_id' => env('CLOUDFLARE_ACCOUNT_ID'),
],
'gotenberg' => [
'url' => env('GOTENBERG_URL', 'http://localhost:3000'),
],
'dompdf' => [
'is_remote_enabled' => env('LARAVEL_PDF_DOMPDF_REMOTE_ENABLED', false),
'chroot' => env('LARAVEL_PDF_DOMPDF_CHROOT'),
],
'job' => \Spatie\LaravelPdf\Jobs\GeneratePdfJob::class,
];
```
Laravel PDF is ideal for generating invoices, reports, contracts, receipts, and any document requiring PDF output in Laravel applications. The driver-based architecture allows you to choose the best backend for your infrastructure - use Browsershot for full CSS support with local Chrome, Cloudflare for serverless deployments, Gotenberg for containerized environments, or DOMPDF for simple PDFs without external dependencies.
The package follows Laravel conventions with its fluent API, Blade integration, filesystem abstraction support, and queue compatibility. Combined with the comprehensive testing utilities, it provides a complete solution for PDF generation that scales from simple documents to complex, high-volume PDF workflows. The macroable PdfBuilder class and custom driver support ensure you can extend the package to meet any specialized requirements.