Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

If a Spatie Laravel PDF command works in CLI but a browser request fails, test the route and response separately from the PDF renderer. Start with a route feature test using Pdf::fake(). If that passes, investigate the driver and executable paths available to the web server process; they may differ from the CLI environment. If the browser receives a PDF but downloads it, check whether your controller calls download(). The exact cause depends on the HTTP response, logs, deployed configuration, and PDF contents.

First identify what “fails” means

A PDF route has at least three separate points of failure: Laravel may not route or authorize the request; the configured driver may not generate a PDF; or a generated PDF may be delivered or rendered differently than expected. A download is not the same failure as an HTTP 500, and a PDF with missing charts is not necessarily a route problem.

For one failing request, record the requested URL, HTTP status, response headers, relevant Laravel log entry, and what the browser actually receives: an HTML error, an empty response, a PDF download, or a PDF that opens but lacks content. Spatie documents controller responses that display PDFs inline or force a download, so inspect the response behavior before assuming the renderer is at fault: Responding with PDFs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Test route and controller wiring without launching a renderer

Use Laravel’s HTTP test client and Spatie’s PDF fake to establish whether the named route, controller, and PDF response are wired correctly. This isolates HTTP behavior from Chrome, Node.js, and the rest of the rendering stack.

use SpatieLaravelPdfFacadesPdf;

it('returns the invoice PDF from its route', function () {
    Pdf::fake();

    $response = $this->get(route('invoices.pdf', $invoice));

    $response->assertOk();
    Pdf::assertRespondedWithPdf($response, function ($pdf) {
        $pdf->contains('Invoice');
    });
});

Adapt the route name, model, and expected content to your application. The assertion verifies the PDF response through the fake; it does not prove that a real browser renderer can run in production. Spatie’s introduction includes this route-testing pattern: Laravel PDF introduction.

If the test fails

  • Confirm the route is registered and the route name and parameters match the request.
  • Check model binding, middleware, authentication, authorization, and validation.
  • Verify that the controller executes and returns the PDF response expected by the test.
  • Use the failing response and Laravel logs to find the HTTP-layer exception before changing browser binaries.

These checks address route and response wiring. A passing fake-based test moves attention to real renderer execution or the resulting document.

Compare the web runtime with the CLI runtime

Spatie Laravel PDF supports multiple drivers. Browsershot is the default and requires Node.js and Chrome or Chromium. A successful artisan command shows that the CLI invocation could use its configured runtime; it does not establish that PHP-FPM, a queue worker, a container, or another web-serving process can find and execute the same programs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Spatie’s configuration includes settings for the driver and for Node, npm, Chrome, node modules, binary and include paths, temporary files, and sandbox behavior. Review the configuration actually deployed to the web process, rather than relying only on a developer’s local .env. See package requirements and driver configuration.

Check these differences in the failing process

  • Driver: confirm which driver the web request uses, and whether it matches the CLI path that succeeds.
  • Executable paths: check that the web process can locate Node.js and Chrome or Chromium. Configure explicit deployed paths when automatic discovery or PATH is unreliable.
  • User and permissions: compare the process user, executable permissions, access to required files, and ability to write to temporary directories.
  • Environment and container: verify environment variables and that the deployed image contains the required runtime and modules. The web process may not inherit an interactive shell’s environment.
  • Sandbox settings: confirm that the configured browser sandbox behavior is appropriate for the process and deployment.

The likely explanation in this branch is a runtime or configuration difference, but that is a diagnosis to verify—not a universal cause of browser-only failures. Use the deployed process’s logs and configuration to establish it.

Check whether the response is inline or a forced download

If the request returns a valid PDF but the browser downloads it rather than displaying it, inspect the controller’s response method. Spatie documents inline display as the default; calling download() forces a download. The package also supports assigning a filename.

use SpatieLaravelPdfFacadesPdf;

return Pdf::view('pdf.invoice', ['invoice' => $invoice])->name('invoice.pdf');

For an intentional download, use the documented download response instead:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
return Pdf::view('pdf.invoice', ['invoice' => $invoice])
    ->name('invoice.pdf')
    ->download();

See Spatie’s response documentation. If the response is an error page or has a failing status, fix that HTTP or rendering error rather than changing disposition.

Fix missing content caused by asynchronous JavaScript

A request can return a valid PDF while charts, maps, fonts, or other content are absent because the view was captured before asynchronous work finished. Rather than adding an arbitrary sleep, signal readiness from the page and have the PDF builder wait for that condition.

For example, the page can set a readiness flag when its required content has loaded:

<script>
  // Set this only after the page's required asynchronous content is ready.
  window.pdfReady = false;

  loadReportData().then(() => {
    renderReport();
    window.pdfReady = true;
  });
</script>

Then configure the builder to wait for the expression supported by the installed driver:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
return Pdf::view('reports.monthly', ['report' => $report])
    ->waitUntilReady('window.pdfReady === true');

Spatie documents waiting for a readiness expression and setting a timeout; the default readiness wait is up to 30 seconds. The documented mechanism works with Browsershot, Chrome, and Gotenberg. Check the installed package version and driver documentation for the precise API and usage: Waiting for readiness. Readiness addresses capture timing, not route matching or missing executable permissions.

Choose a different driver only for a concrete deployment need

Spatie lists Browsershot, Chrome, Cloudflare, DOMPDF, Gotenberg, and WeasyPrint. Driver choice affects where rendering runs, which runtime it needs, whether JavaScript-heavy templates work, and what operational dependencies the application must maintain. Compare the requirements of the document and deployment before switching; a new driver will not repair an unrelated route or response bug.

Driver or approach What the documented facts establish Questions to check for your deployment
Browsershot The default driver; requires Node.js and Chrome or Chromium. Can the web process execute both binaries, access its files, and use the configured paths and sandbox settings?
Chrome The package documents a Chrome driver; its driver guide states Chrome/Chromium 65+ as a requirement. Does the deployed browser version and runtime satisfy the guide, and does the driver support the document options you rely on?
Cloudflare Uses the Browser Run API, avoiding local Node.js or Chrome; requires credentials and a remote service. Can the application reach the external service, securely supply credentials, and accept its operational constraints? See Cloudflare driver guide.
DOMPDF A pure-PHP option; it does not provide JavaScript execution. Can the document be rendered without browser-based JavaScript, and does its layout meet your needs?
Gotenberg or WeasyPrint Both are listed as supported drivers. Check the driver-specific runtime or service requirements and confirm support for the PDF options your document uses.

The driver distinctions above are documented by Spatie in its requirements and configuration pages. Beyond those facts, assess where rendering occurs (inside your process, in a managed service, or remotely), JavaScript and CSS needs, filesystem and process permissions, outbound network access, credentials, latency, service limits, and feature compatibility. Do not assume one driver is best for every application.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

“Or skip the browser setup:” use a screenshot API for web-page captures

If your actual task is capturing a website page rather than generating a PDF from a Laravel view, ScreenshotNeo is a website screenshot API and MCP server. A single GET request returns a PNG, JPEG, WebP, or PDF. It is not a drop-in replacement for a Laravel PDF route or a renderer for your application’s Blade view; use it for URL-based page captures.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for options and setup. Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report 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 monthly with no card; paid plans start at $5 for 3,000 shots.

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

Troubleshooting by symptom

Symptom Most useful next check
Route returns 404 or the wrong page Test the named route and request parameters; verify route registration, model binding, and middleware.
Route test fails before a real renderer is involved Inspect controller execution, authorization, validation, and response construction; use the exception or response body to locate the HTTP-layer failure.
Fake-based route test passes, live request fails Inspect the configured driver, web-process logs, binary paths, permissions, environment, and temporary-directory access.
CLI succeeds but web request cannot launch the browser Compare the CLI and web process users, PATH, executable paths, installed runtime, and sandbox configuration.
Browser downloads a valid PDF Check whether the controller calls download(); use the inline response method when display is intended.
PDF opens but asynchronous content is missing Signal when the view is genuinely ready and use the documented readiness wait instead of guessing a delay.
Cloud rendering fails after switching drivers Verify configured credentials and outbound access to the remote service, then inspect driver-specific errors.

Version and operational notes

The cited pages are for Spatie Laravel PDF v2 unless a version-specific guide is linked. Spatie’s requirements page states PHP 8.2+ and Laravel 11+; the Chrome driver guide specifies Chrome/Chromium 65+ for that driver. Treat these as the package documentation’s versioned requirements, not a guarantee that any deployment with those versions has a working process configuration. Check the requirements and driver guide for the version you install: Requirements and Using the Chrome driver.

For reliability, distinguish request-time rendering from background generation in your architecture, and monitor the actual failure mode: HTTP status, exception, renderer exit details, or incomplete document. A route test with a fake is fast and isolates wiring; it cannot measure real rendering latency or validate deployed executables. A remote driver may remove local browser installation work but introduces credentials, network dependence, and service-specific constraints. Choose based on the application’s rendering requirements and the environment you can operate.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.