PHP Guide

HTML to PDF in PHP

Generate PDFs from HTML in Laravel, Symfony, or plain PHP — without mPDF, dompdf, or wkhtmltopdf. No system dependencies, no Composer package bloat. One API call.

Why not mPDF or dompdf?

mPDF and dompdf are pure-PHP PDF renderers that parse HTML and CSS themselves — not a real browser. Modern CSS (Flexbox, Grid, custom fonts, CSS variables) either doesn't work or renders incorrectly. Debugging layout differences between the browser and the PDF is a common time sink.

Papyr renders with Chromium — the same engine as Chrome. Design your document in a browser, ship it as a PDF. No surprises.

Plain PHP

No library required — works with just the standard library.

PHP
<?php

function htmlToPdf(string $html): string
{
    $response = file_get_contents(
        'https://api.getpapyr.dev/v1/render/pdf',
        false,
        stream_context_create([
            'http' => [
                'method'  => 'POST',
                'header'  => [
                    'Authorization: Bearer ' . $_ENV['PAPYR_API_KEY'],
                    'Content-Type: application/json',
                ],
                'content' => json_encode([
                    'html'    => $html,
                    'options' => [
                        'format' => 'A4',
                        'margin' => ['top' => '20mm', 'right' => '20mm',
                                     'bottom' => '20mm', 'left' => '20mm'],
                    ],
                ]),
            ],
        ])
    );

    if ($response === false) {
        throw new RuntimeException('PDF generation failed');
    }

    return $response;
}

// Usage — save to disk
$pdf = htmlToPdf('<h1>Invoice #1042</h1>');
file_put_contents('invoice.pdf', $pdf);

// Usage — stream to browser
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="invoice.pdf"');
echo htmlToPdf($html);

Laravel controller

Use Laravel's HTTP client and Blade templating. Store the key in config/services.php.

Laravel
<?php
// app/Http/Controllers/InvoiceController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Http;

class InvoiceController extends Controller
{
    public function pdf(Request $request, int $id): Response
    {
        $invoice = Invoice::findOrFail($id);

        // Use Laravel's Blade templating
        $html = view('invoices.pdf', compact('invoice'))->render();

        $response = Http::withToken(config('services.papyr.key'))
            ->post('https://api.getpapyr.dev/v1/render/pdf', [
                'html'    => $html,
                'options' => ['format' => 'A4'],
            ]);

        if ($response->failed()) {
            abort(500, 'PDF generation failed');
        }

        return response($response->body(), 200, [
            'Content-Type'        => 'application/pdf',
            'Content-Disposition' => "attachment; filename=invoice-{$invoice->number}.pdf",
        ]);
    }
}

Laravel + Guzzle + S3

Generate and store the PDF directly in S3 via Laravel Storage.

Laravel + Guzzle
<?php
// Using Guzzle (if preferred over Laravel Http)

use GuzzleHttp\Client;

$client = new Client();

$response = $client->post('https://api.getpapyr.dev/v1/render/pdf', [
    'headers' => [
        'Authorization' => 'Bearer ' . env('PAPYR_API_KEY'),
        'Content-Type'  => 'application/json',
    ],
    'json' => [
        'html'    => $html,
        'options' => [
            'format'    => 'A4',
            'landscape' => false,
        ],
    ],
]);

$pdf = (string) $response->getBody();

// Store in S3 via Laravel Storage
Storage::disk('s3')->put("invoices/{$invoiceId}.pdf", $pdf);

Get your API key

Free tier: 100 PDFs/month. No credit card required.