# HTML to PDF in Laravel HTML to PDF in Laravel: render Blade views with laravel-dompdf, Browsershot, spatie/laravel-pdf, or one Http::withToken() call to an API. Laravel makes it easy to render a Blade view to HTML. Turning that HTML into a PDF is where you have to choose. A pure-PHP renderer is simple to install but ignores modern CSS, while headless Chrome renders perfectly but has to run somewhere. This guide compares the main packages, then shows a version with no browser on your server. **Quick answer.** Render the view, post it to the API with Laravel's HTTP client, and return the bytes: ```php $response = Http::withToken(config('services.html_pdf.key')) ->post('https://html-pdf.com/v1/pdf', ['html' => view('invoices.pdf', ['invoice' => $invoice])->render()]); return response($response->body(), 200, ['Content-Type' => 'application/pdf']); ``` ## Laravel PDF packages compared This table shows which engine each option uses and what it needs on your server. | Package | Engine | Flexbox / grid | Server requirements | |---|---|---|---| | barryvdh/laravel-dompdf | Dompdf (pure PHP) | No | None beyond PHP extensions | | spatie/browsershot | Puppeteer + Chrome | Yes | Node.js, Puppeteer, Chrome | | spatie/laravel-pdf | Driver-based: Browsershot, Cloudflare, DomPdf, Gotenberg | Depends on driver | Depends on driver | | Http client + html-pdf.com | Headless Chromium, hosted | Yes | Nothing | ## Option 1: barryvdh/laravel-dompdf This is the most installed choice and the quickest to set up. It wraps Dompdf in a Laravel facade. ```bash composer require barryvdh/laravel-dompdf ``` ```php use Barryvdh\DomPDF\Facade\Pdf; public function download(Invoice $invoice) { return Pdf::loadView('invoices.pdf', ['invoice' => $invoice]) ->setPaper('a4') ->download("invoice-{$invoice->id}.pdf"); } ``` Dompdf implements roughly CSS 2.1, so layouts built with flexbox, grid or Tailwind utilities that depend on them collapse. Use tables and floats in PDF views instead. Large documents can be slow and memory-hungry. Remote images need the `isRemoteEnabled` option, which you should only turn on for HTML you trust. ## Option 2: spatie/browsershot This option gives you PDFs that match Chrome's print output. Browsershot drives headless Chrome through Puppeteer. ```bash composer require spatie/browsershot npm install puppeteer ``` ```php use Spatie\Browsershot\Browsershot; $html = view('invoices.pdf', ['invoice' => $invoice])->render(); $pdf = Browsershot::html($html) ->format('A4') ->margins(15, 15, 15, 15) ->showBackground() ->pdf(); // raw bytes return response($pdf, 200, ['Content-Type' => 'application/pdf']); ``` The cost is your infrastructure. Every server or worker needs Node.js, Puppeteer, a Chrome build and its system libraries, plus enough memory to start a browser per render. Forge and Docker setups can handle it. Shared hosting and some serverless platforms can't. ## Option 3: spatie/laravel-pdf This option gives you a Laravel-style API on top of a choice of drivers. Browsershot is the default. Version 2 added Cloudflare Browser Rendering and DomPdf drivers, and v2.1 added Gotenberg. ```php use Spatie\LaravelPdf\Facades\Pdf; public function download(Invoice $invoice) { return Pdf::view('invoices.pdf', ['invoice' => $invoice]) ->format('a4') ->name("invoice-{$invoice->id}.pdf") ->download(); } ``` It is a clean API, but each driver keeps its own requirements. That means Chrome for Browsershot, a Cloudflare account, a running Gotenberg container, or Dompdf's CSS limits. ## Or skip the server: Http::withToken() to html-pdf.com This option gives you Chrome-quality PDFs with nothing to install. html-pdf.com runs headless Chromium for you. Your app renders the Blade view, sends the HTML with Laravel's HTTP client, and gets the PDF bytes back in the response. Get a key, then open the link we email you to confirm your address. That adds 100 free credits. ```bash curl -X POST https://html-pdf.com/v1/signup -H "Content-Type: application/json" -d '{"email": "you@example.com"}' ``` ```php // config/services.php 'html_pdf' => [ 'key' => env('HTML_PDF_KEY'), ], ``` ```php authorize('view', $invoice); $html = view('invoices.pdf', ['invoice' => $invoice])->render(); $response = Http::withToken(config('services.html_pdf.key')) ->timeout(60) ->post('https://html-pdf.com/v1/pdf', [ 'html' => $html, 'format' => 'A4', 'margin' => '15mm', 'max_pages' => 20, // longer documents fail without charge 'footer_html' => '