Free tools Windows power users keep installed
One-click scans. No signup required.
If a Spatie Laravel PDF command works in CLI but its route fails in a browser, diagnose the HTTP route and the PDF renderer as separate layers. First test the named route with Laravel’s HTTP test client and Pdf::fake(). If that passes, check whether the web-server PHP process can find and run the renderer’s dependencies; a CLI success does not prove it can. If the browser gets a PDF but downloads it, check whether your controller calls download().
First identify what “fails” means
A browser symptom alone does not tell you whether the route, renderer, response mode, or document content is at fault. Record the exact route URL and request method, HTTP status, response headers, Laravel exception or log entry, and what the browser actually receives.
- An HTML error page or non-success status points first to routing, middleware, controller execution, or an exception.
- An empty response or failed request needs inspection of the HTTP response and application logs before assuming Chrome is the cause.
- A PDF that downloads rather than opening is a response-disposition question.
- A valid PDF missing charts, fonts, or other late-loaded content suggests a rendering-readiness issue.
- A route that fails only when it performs live rendering warrants checking the renderer runtime available to the web process.
Spatie documents returning a PDF directly from a controller, with inline display as the default and download() as an explicit download mode. See Spatie’s response options.
Test route wiring without launching a renderer
Use a feature test to check whether Laravel can reach the named route, execute its controller and return the expected PDF response. Spatie’s testing example uses Pdf::fake() so the test does not need to launch a real browser engine. For example, adapt the route name and expected text to your application:
Recommended Free Tools
#1 Best Overall
<?php
namespace TestsFeature;
use SpatieLaravelPdfFacadesPdf;
use TestsTestCase;
class InvoicePdfTest extends TestCase
{
public function test_invoice_route_returns_a_pdf(): void
{
Pdf::fake();
$response = $this->get(route('invoices.pdf', ['invoice' => 123]));
$response->assertOk();
Pdf::assertRespondedWithPdf('Invoice 123');
}
}
Confirm that the package version and test setup in your application use the same facade and assertion API as the installed version. The example is a diagnostic pattern, not a substitute for checking your route’s real authorization or data behavior. Spatie’s introduction shows the route-level fake and PDF assertion pattern: Laravel PDF introduction and testing example.
If this test fails, work through Laravel’s HTTP path before touching Chrome or Node:
- Check route registration with
php artisan route:list; verify the URI, HTTP method, and route name. - Confirm the route parameters satisfy route constraints and model binding, and that the requested record exists.
- Check authentication, authorization, CSRF requirements where relevant, and other middleware. A browser request may have a different session or credentials from a local CLI operation.
- Inspect controller exceptions and logs, then verify the response construction independently of rendering.
These are practical checks for the HTTP layer: a fake-PDF test that fails has not yet established a renderer problem.
If the route test passes, compare CLI and web renderer environments
Spatie Laravel PDF’s default driver is Browsershot, which requires Node.js and Chrome or Chromium. The web PHP worker may run under a different user, PATH, filesystem, container image, or environment from the shell that runs an Artisan command. That makes an environment mismatch a useful hypothesis, not a guaranteed explanation for every browser failure. Spatie lists the package’s requirements and driver configuration.
- Identify the active driver. Check the deployed Laravel PDF configuration, not just a developer workstation’s
.env. Spatie supports explicit driver selection. - Check the web process’s executable access. Verify that the PHP-FPM or other web worker user can execute the configured Node and Chrome/Chromium binaries. A path visible in your interactive shell may not be on the worker’s PATH.
- Verify filesystem access. Confirm the worker can read required binaries and modules and can write to the configured temporary locations. Check permissions under the actual service user.
- Use explicit paths when discovery is unreliable. Spatie’s configuration includes settings for Node, npm, Chrome, node_modules, binary and include paths, temporary paths, and sandbox behavior. Set values appropriate to the deployed image or host, then confirm the web worker can use them.
- Check deployment parity. If CLI and web requests run in different containers or releases, compare their installed runtimes and configuration rather than assuming they share the same dependencies.
Do not treat a local command’s success as evidence that production has the same binaries or permissions. Conversely, if the worker can execute the configured runtime and a live render still fails, use the exception and logs to continue diagnosis instead of repeatedly changing PATH settings.
Check whether the browser should display or download the PDF
Spatie’s documented PDF response is inline by default. Calling download() forces a download. If the PDF file is valid but the browser saves it, inspect the controller chain for that method and for any response middleware or headers that change disposition.
Rank #3
use SpatieLaravelPdfFacadesPdf;
Route::get('/invoices/{invoice}/pdf', function (Invoice $invoice) {
return Pdf::view('invoices.pdf', ['invoice' => $invoice])
->name('invoice-'.$invoice->id.'.pdf');
});
In a real controller, return the generated response as documented. Use the package’s filename method together with download() when the desired behavior is a named attachment; omit the forced-download call when you want inline viewing. Consult Spatie’s response documentation for the installed package’s exact method usage. If the response is HTML or an error status rather than a PDF, resolve that response first.
For missing content, wait for the view to be ready
Generating a PDF successfully does not guarantee that JavaScript-driven parts of the page finished loading before capture. Charts, maps, or other asynchronously populated content can be absent even when the route returns a PDF. Spatie provides a readiness signal and waitUntilReady() rather than requiring arbitrary fixed delays.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsFor a JavaScript-driven view, signal readiness only after the content you need is actually available, then configure the PDF builder to wait for the matching expression. Spatie documents a default readiness wait of up to 30 seconds and supports a custom expression and timeout. Readiness support is documented for Browsershot, Chrome, and Gotenberg; check the driver you use and the package’s readiness instructions.
Rank #4
This addresses capture timing, not route registration or missing executable access. If the PDF is entirely absent, return to the earlier HTTP and renderer checks.
Choose another driver only when the deployment calls for it
Spatie lists Browsershot, Chrome, Cloudflare, DOMPDF, Gotenberg, and WeasyPrint drivers. Decide based on where rendering should run, required runtimes, whether the template needs JavaScript or modern CSS behavior, filesystem and sandbox constraints, outbound network access, credentials, latency, service limits, and the options your document depends on. Driver details are in Spatie’s configuration guide.
| Driver or approach | What to weigh | Documented distinction |
|---|---|---|
| Browsershot | Local runtime availability, executable paths, permissions, and sandboxing | The default driver; requires Node.js and Chrome/Chromium. Requirements |
| Chrome | Chrome runtime and the driver’s version requirements | Spatie’s Chrome-driver guide lists Chrome/Chromium 65+ and the package requirements list PHP 8.2+ and Laravel 11+; verify compatibility against your installed package version. Chrome driver guide |
| Cloudflare | Remote service dependency, account credentials, outbound access, and service constraints | Uses Cloudflare’s Browser Run API and avoids local Node.js or Chrome, but requires credentials. Cloudflare driver guide |
| DOMPDF | Whether your layout can work without browser JavaScript execution | A pure-PHP option for simpler layouts; it does not provide JavaScript execution. |
| Gotenberg or WeasyPrint | Service/runtime operations and feature compatibility with your document | Listed as supported drivers; compare their specific requirements and supported options in the package documentation. |
A driver change is not a generic repair. First establish whether the failure is in Laravel routing, the current renderer’s deployed environment, response disposition, or page readiness; then decide if another runtime better fits your deployment.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Best Value
Or skip the browser setup
If your separate need is to capture an ordinary website as an image or PDF—not to render Laravel Blade views inside your application—ScreenshotNeo provides a website screenshot API and MCP server. One GET request can return PNG, JPEG, WebP, or PDF. It is not a replacement for diagnosing or rendering a Spatie Laravel PDF route.
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 request options and response details. ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free.
Common failure patterns and next checks
| Symptom | Likely layer to inspect | Next check |
|---|---|---|
| Named-route feature test fails with fake PDF | Laravel HTTP path | Route list, method and name, parameters, model binding, middleware, controller exception, response construction. |
| Fake test passes, live route fails | Renderer execution or deployed config | Active driver, worker user, executable paths, runtime availability, temporary-directory access, container parity, and logs. |
| PDF arrives but is saved as a file | Response disposition | Look for download() or headers forcing attachment; use the intended inline or download response. |
| PDF opens but dynamic elements are blank | View readiness | Signal readiness after asynchronous work and use waitUntilReady() with a suitable expression and timeout. |
| Works locally, fails after deploy | Production runtime and filesystem | Compare driver configuration, binary locations, worker permissions, environment variables, and image contents in the deployed environment. |
For a version-specific requirement check, the package documentation currently cited for this guide identifies PHP 8.2+ and Laravel 11+ in its requirements and Chrome/Chromium 65+ for the Chrome driver. Treat these as documented software requirements, not a guarantee that every newer package version or environment has identical constraints; verify against the version installed in your application.
Frequently Asked Questions
Does a successful Artisan PDF command prove the browser route should work?
No. The CLI and web PHP processes can differ in runtime paths, user permissions, environment, or deployed image. Test the route separately, then verify the renderer from the web process.
Should I switch from Browsershot as soon as the route fails?
No. First separate a route/controller failure from renderer execution, response disposition, and view readiness. Change drivers only if the deployment or document requirements justify it.
Quick Recap
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.




