How to convert HTML to PDF in PHP
Dompdf is the common choice in PHP and Laravel. Here is working code for it, where its CSS support stops, and the API alternative.
By Saurav N, senior software engineer · Updated
· 5 min readDompdf
Dompdf is pure PHP, installs with Composer (composer require dompdf/dompdf) and needs no browser. In Laravel, packages such as barryvdh/laravel-dompdf wrap it.
It supports most CSS 2.1 and some CSS 3, but not flexbox or grid, so build layouts with tables and floats. Embed fonts that cover your scripts, or some characters render as boxes.
<?php
require 'vendor/autoload.php';
use Dompdf\Dompdf;
$dompdf = new Dompdf();
$dompdf->loadHtml('<h1>Invoice INV-2026-0142</h1><p>Total Rs 49,402.50</p>');
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
file_put_contents('invoice.pdf', $dompdf->output());An HTML to PDF API from PHP
An API renders with Chrome, so modern CSS works, and PHP only sends the data.
<?php
$ch = curl_init('https://templater.nestutils.com/v1/pdfs/render?wait=20');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('TEMPLATER_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'template' => 'gst-invoice',
'returnAs' => 'binary',
'data' => ['invoice' => ['number' => 'INV-2026-0142', 'total' => 49402.5]],
]),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status === 200) {
file_put_contents('invoice.pdf', $body);
} else {
echo $body; // 202: still rendering (poll GET /v1/pdfs/{id}); 4xx: the error envelope
}Which one should you use?
Dompdf is enough for simple, table-based documents rendered on the same server. Reach for Chrome, directly or through an API, when layouts use modern CSS or the output must match the browser.
An API also suits you when: You want the same template edited by your team in a browser, previewed on real data, versioned, and rendered without running Chrome yourself. You pay per render instead of per server.
Questions
Why does the rupee sign (₹) show as a box?
The font has no glyph for it. Embed a font that does, such as Noto Sans or DejaVu Sans, and use it in your CSS.
Does Dompdf support page breaks?
Yes: page-break-before, page-break-after and page-break-inside: avoid work on block elements.
Can I use Blade templates?
Yes. Render the view to a string with view(...)->render() and pass it to loadHtml().