ScreenshotNeo

BlogHTML to image & PDF

How to Generate a Webpage PDF in Laravel with Browsershot

Generate a webpage PDF in Laravel with Spatie Browsershot. Configure Chrome, set page options, handle failures, and choose between URL and HTML input.

By the ScreenshotNeo team4 October 20268 min read

Use Spatie Browsershot to render an existing webpage with Browsershot::url($url)->savePdf($path). If Laravel has already generated the markup, use Browsershot::html($html)->savePdf($path). Both approaches need a working Node.js runtime and Chrome or Chromium where the PDF job runs. For a Blade view and Laravel-oriented document workflow, Spatie Laravel PDF provides a facade with a Browsershot driver.

This guide covers direct Browsershot usage, the Laravel PDF integration, page layout options, runtime setup, security, troubleshooting, and a hosted screenshot-to-PDF alternative. For package-specific APIs, check the Browsershot PDF documentation and the Laravel PDF installation and setup guide against the versions in your project.

1. Choose URL rendering or HTML rendering

Input Use it when Example
URL You need a PDF of a page already served by your application or another trusted site. Browsershot::url($url)
HTML Your application has generated the markup and should render that content directly. Browsershot::html($html)
Local file The HTML is already stored as a local file accessible to the rendering process. Browsershot documents loading HTML from a local file path.

URL input lets the browser load the page’s stylesheets, fonts, images, and scripts as the page normally does. HTML input is useful for generated documents, but referenced assets still need to be reachable by the browser process. Use absolute asset URLs or otherwise ensure the browser can resolve them.

2. Install and prepare the rendering runtime

  1. Install the Browsershot package in the Laravel application using the installation instructions for the version you have chosen.
  2. Install Node.js and a Chrome or Chromium binary in the environment that executes the render.
  3. Make sure the PHP process can find those binaries. A web request process, queue worker, and local shell may have different paths.
  4. If using Laravel PDF, publish and review its configuration with php artisan vendor:publish --tag=pdf-config.
  5. Check package requirements against your PHP and Laravel versions. The cited Laravel PDF v2 requirements specify PHP 8.2+ and Laravel 11+; confirm the requirements for your locked version.

In containers and production deployments, include the runtime dependencies in the image or rendering environment used by workers. Installing Chrome on a developer machine does not make it available to a separate queue container.

3. Generate a PDF directly with Browsershot

For a trusted webpage URL:

<?php

use Spatie\Browsershot\Browsershot;

$url = 'https://example.com/report';
$outputPath = storage_path('app/reports/report.pdf');

Browsershot::url($url)->savePdf($outputPath);

The destination directory must exist and be writable by the PHP process. Browsershot also documents saving PDF output through save() when the destination path ends in .pdf; savePdf() makes the intent explicit.

For markup generated by Laravel:

<?php

use Spatie\Browsershot\Browsershot;

$html = '<!doctype html><html><body><h1>Monthly report</h1><p>Prepared by Laravel.</p></body></html>';
$outputPath = storage_path('app/reports/monthly-report.pdf');

Browsershot::html($html)->savePdf($outputPath);

When the application needs the generated PDF data rather than a saved file, Browsershot documents base64pdf(). Account for the memory cost of holding the encoded result, especially for large documents.

4. Render a Blade view with Laravel PDF

Spatie Laravel PDF is a separate Laravel integration. It supports a Browsershot driver, documented as its default, and lets a document customize the Browsershot instance with withBrowsershot(). Follow the API for your installed version; a typical pattern is:

<?php

use Spatie\LaravelPdf\Facades\Pdf;

return Pdf::view('pdf.report', ['report' => $report])
    ->withBrowsershot(function ($browsershot) {
        $browsershot->format('A4');
    })
    ->download('report.pdf');

The facade renders the Blade view, while withBrowsershot() applies per-document browser settings after the configured defaults. Confirm the namespace and available methods for the version in composer.lock. Laravel PDF configuration exposes settings for Node, npm, Chrome, Node modules, binary and temporary directories, as well as no_sandbox. Set explicit paths when the runtime cannot locate dependencies through its environment.

5. Set page size, margins, and print behavior

Browsershot documents PDF controls including standard paper formats such as A4 and Letter, custom dimensions, margins, headers and footers, background rendering, transparent background, tagged output, landscape orientation, scale from 0.1 to 2, and selected page ranges. Use only the controls needed for the document, and consult the API reference for exact method signatures in your package version.

<?php

use Spatie\Browsershot\Browsershot;

Browsershot::url('https://example.com/report')
    ->format('A4')
    ->landscape()
    ->margins(12, 10, 12, 10)
    ->showBackground()
    ->savePdf(storage_path('app/report.pdf'));

Dimensions and margin values are interpreted by the Browsershot API; verify units and supported method names in the version you use. For a repeatable document layout:

  • Choose a paper format or explicit dimensions that match the intended reader and printer.
  • Set margins deliberately so body content does not collide with page edges or headers and footers.
  • Enable background printing if the document relies on colored backgrounds or background graphics.
  • Use landscape orientation for genuinely wide tables or diagrams.
  • Use scaling sparingly; it can shrink text and alter line breaks across the whole document.
  • Use page ranges when only a subset of a long document is required.
  • Check page breaks, font loading, and external images in the actual worker environment.

6. Keep PDF rendering secure

Rendering a URL gives the browser network access, and rendering HTML can execute scripts or load referenced resources. The Browsershot documentation places validation responsibility on the caller: only pass URLs and HTML that you trust. Do not pass arbitrary user-controlled destinations or markup directly to a browser renderer. Validate and constrain inputs before rendering, and consider what internal network locations the render environment can reach.

7. Troubleshoot common failures

Symptom Likely cause What to check
Node or npm executable not found The PHP process has a different PATH, or Node is absent in the worker/container. Install Node where the job runs and set the explicit Node/npm paths in Laravel PDF configuration when needed.
Chrome/Chromium cannot launch Browser binary is absent, configured at the wrong path, or unavailable in the execution environment. Check the installed binary path and configure Chrome explicitly. Review the environment’s sandbox requirements and the package’s no_sandbox setting.
Works in a web request, fails in a queue The worker uses a separate image, user, PATH, permissions, or temporary directory. Install/configure dependencies in the worker environment and ensure its user can write to output and temporary directories.
PDF is missing images, fonts, or styles Assets are inaccessible to Chrome, blocked, or not ready when capture begins. Use reachable asset URLs, check authentication and network access, and ensure fonts and resources are available before rendering.
Output has unexpected page breaks or clipping Page size, margins, orientation, scaling, or print styles do not match the content. Adjust the PDF options and CSS for print, then inspect the generated output in the target runtime.
Cannot write the result The parent directory is missing or the PHP user lacks write permission. Create the directory and grant the worker appropriate write access; verify the configured temporary path too.
Unexpected content or unsafe network access Untrusted URL or HTML was rendered. Restrict inputs to trusted content and validate destinations before invoking Browsershot.

8. Performance, reliability, and cost considerations

Each PDF render requires a browser runtime and page loading. The time and resources depend on the page, its assets, scripts, and document size; the cited sources do not establish a universal speed or fidelity ranking. For reliability, run renders in the same environment that will serve production jobs, ensure temporary and output storage are writable, and account for failures in the application flow. For large PDFs, avoid unnecessarily keeping multiple full document copies in PHP memory; use a file-oriented workflow when appropriate.

With local Browsershot, account for the infrastructure and maintenance of Node.js, Chrome/Chromium, and the workers that run them. Laravel PDF documents other driver choices, including Chrome, Cloudflare, DOMPDF, Gotenberg, and WeasyPrint. Compare them based on layout and CSS needs, local runtime constraints, and whether a remote or separate rendering service fits your deployment; the reviewed sources do not support a universal winner.

9. Or skip the browser setup

If the result you need is a screenshot or PDF capture of a live page, ScreenshotNeo offers a website capture API and MCP server. Its one-call PDF endpoint accepts a URL; see the ScreenshotNeo API documentation for PDF options and parameters.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -d format=pdf -o page.pdf
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com", "format": "pdf"},
    timeout=90,
)
r.raise_for_status()
open("page.pdf", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com',
  format: 'pdf',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`ScreenshotNeo returned ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('page.pdf', Buffer.from(await res.arrayBuffer())));

ScreenshotNeo removes supported cookie banners, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, with response headers reporting the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 shots each month with no card; paid plans start at $5 for 3,000 shots. Every feature is available on every plan. This is a hosted capture option for live URLs; use Browsershot when you need your Laravel process to render generated Blade content directly.

Sign up for 1,000 free screenshots a month, with no card required.

10. FAQ

Can Browsershot save directly to a PDF?

Yes. Use savePdf($path), or the documented save() method with a .pdf destination.

Can I return PDF data without writing a file first?

Browsershot documents base64pdf() for workflows that need encoded PDF data.

Does this require a browser installed on the web server?

It requires Node.js and Chrome or Chromium in the environment that runs the rendering job. That may be a worker or container rather than the web server process itself.

Can I use Browsershot with a Blade view?

Use Spatie Laravel PDF’s view and facade workflow with its Browsershot driver, or render the Blade view to HTML and pass trusted markup to standalone Browsershot.

Can it render an arbitrary URL supplied by a user?

Do not treat arbitrary URLs or HTML as safe. Validate inputs and render only trusted content, as the Browsershot documentation advises.

References