DEV Community

Custodia-Admin
Custodia-Admin

Posted on • Originally published at pagebolt.dev

How to take screenshots and generate PDFs in PHP (without wkhtmltopdf)

How to Take Screenshots and Generate PDFs in PHP (Without wkhtmltopdf)

PHP PDF generation has always been painful. wkhtmltopdf requires a binary installation and struggles with modern CSS and JavaScript. Dompdf is pure PHP but can't render JavaScript-heavy pages. mPDF is similar. Browsershot (Spatie) wraps Puppeteer, which means Node.js on your server.

Here's the clean path: one HTTP request, binary response, no system dependencies.

Screenshot from a URL

<?php

function screenshot(string $url): string
{
    $ch = curl_init('https://pagebolt.dev/api/v1/screenshot');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'x-api-key: ' . $_ENV['PAGEBOLT_API_KEY'],
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'url' => $url,
            'fullPage' => true,
            'blockBanners' => true,
        ]),
    ]);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

// Save to disk
file_put_contents('screenshot.png', screenshot('https://example.com'));
Enter fullscreen mode Exit fullscreen mode

PDF from a URL

function pdfFromUrl(string $url): string
{
    $ch = curl_init('https://pagebolt.dev/api/v1/pdf');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'x-api-key: ' . $_ENV['PAGEBOLT_API_KEY'],
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'url' => $url,
            'blockBanners' => true,
        ]),
    ]);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

file_put_contents('page.pdf', pdfFromUrl('https://yourapp.com/invoice/1042'));
Enter fullscreen mode Exit fullscreen mode

PDF from HTML (replacing wkhtmltopdf / Dompdf)

Render your PHP template to an HTML string first, then send it:

function pdfFromHtml(string $html): string
{
    $ch = curl_init('https://pagebolt.dev/api/v1/pdf');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'x-api-key: ' . $_ENV['PAGEBOLT_API_KEY'],
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode(['html' => $html]),
    ]);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

// Build your HTML however you like
ob_start();
include 'templates/invoice.php';
$html = ob_get_clean();

$pdf = pdfFromHtml($html);
file_put_contents("invoice-{$invoiceId}.pdf", $pdf);
Enter fullscreen mode Exit fullscreen mode

Laravel controller example

use Illuminate\Http\Response;

class InvoiceController extends Controller
{
    public function download(Invoice $invoice): Response
    {
        $html = view('invoices.pdf', compact('invoice'))->render();

        $ch = curl_init('https://pagebolt.dev/api/v1/pdf');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'x-api-key: ' . env('PAGEBOLT_API_KEY'),
                'Content-Type: application/json',
            ],
            CURLOPT_POSTFIELDS => json_encode(['html' => $html]),
        ]);
        $pdf = curl_exec($ch);
        curl_close($ch);

        return response($pdf, 200, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => "attachment; filename=\"invoice-{$invoice->id}.pdf\"",
        ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

No Composer package, no binary, no Node.js. The Blade template renders as normal — just swap the PDF generation step.

Deployment

No buildpacks, no apt-get, no binary layer. Works on shared hosting, Heroku, Laravel Forge, or any PHP environment with outbound HTTPS. Add PAGEBOLT_API_KEY to your .env and deploy as normal.


Try it free — 100 requests/month, no credit card. → Get started in 2 minutes

Top comments (0)