Most Laravel Browsershot PDF failures come from one of four places: the worker cannot find Node.js or Chrome, an upgrade omitted the Browsershot package, Chrome cannot read local assets, or Laravel cannot write or return the generated file. Diagnose the stage that fails, then verify dependencies and paths from the same web or queue process that renders the PDF—not only from your interactive shell.
1. Identify exactly where generation fails
Start by preserving the complete exception message, stack trace, worker log, and the URL or view being rendered. A PDF problem can occur before Chrome starts, while the page is loading, while Chrome writes the PDF, or after a valid PDF has been created but before Laravel stores or returns it.
- Before Chrome starts: suspect missing packages, Node.js, Chrome/Chromium, PATH, permissions, or an invalid executable path.
- During page loading: investigate timeouts, JavaScript errors, authentication, network access, and unreachable assets.
- PDF is created but looks wrong: check CSS, images, fonts, local-file access, and print-specific layout.
- PDF exists but the request fails: isolate storage permissions, temporary directories, response headers, and queue hand-off.
Record the selected Laravel PDF driver and the versions in composer.lock, package-lock.json or equivalent. The official requirements identify the runtime dependencies, but they do not provide a universal exception-to-fix mapping, so the failing stage matters.
2. Verify Node.js and Chrome in the real runtime
The Browsershot driver for Laravel PDF requires Node.js and a Chrome or Chromium executable. These must be available to the PHP process that performs the render. A shell session for your own user may have a different PATH, home directory, container, or permissions than PHP-FPM, a web server, or a queue worker. See the documented requirements at Spatie’s Laravel PDF requirements.
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 →#1 Best Overall
Check from the worker environment
Run equivalent checks as the service account or inside the same container and image used for rendering:
node --version
npm --version
which node
which npm
which google-chrome || which chromium || which chromium-browser
ls -l /absolute/path/to/chrome
On Windows, use where node, where npm, and where chrome. A version command that works in SSH but fails in a queue job indicates an environment mismatch, not a Browsershot rendering defect.
Set explicit paths when discovery is unreliable
Laravel PDF exposes configuration for Node.js, npm, Chrome, the Node modules directory, the Browsershot binary, temporary files, and the no-sandbox setting. Compare those values with the deployed filesystem and the identity running the job. The configuration reference is at the Laravel PDF driver configuration guide.
- Use absolute paths rather than relying on a login-shell PATH.
- Confirm every executable has execute permission and every parent directory is searchable.
- Ensure the temporary directory exists, is writable, and has enough space.
- After changing published configuration or environment variables, clear Laravel’s cached configuration and restart PHP-FPM and queue workers.
- In containers, install the browser in the image that actually runs the worker; installing it only on the host does not make it available inside the container.
The documented no-sandbox option can be necessary in locked-down environments. Use it only when your deployment requires it and understand the security implications of changing Chrome’s sandbox behavior.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →3. Check Laravel PDF and Browsershot package versions
Laravel PDF version 2 moved Browsershot to a suggested dependency. If your application selects the Browsershot driver but does not explicitly install spatie/browsershot, generation can fail with a CouldNotGeneratePdf exception. Follow the official upgrade notes at the v1-to-v2 upgrading guide.
Upgrade checklist
- Inspect the installed Laravel PDF version with Composer and confirm the driver configured by the application.
- Require the Browsershot package explicitly when using that driver, then run Composer’s install/update command in the deployment build.
- Commit the lockfile and deploy the same dependency set to web and queue workers.
- Republish or review the package configuration after an upgrade; do not assume v1 defaults still apply.
- Restart long-running workers so they load the new autoloader and configuration.
Do not “fix” a dependency error by switching drivers without checking what the replacement requires. Every driver has a different runtime model.
4. Fix PDFs with missing CSS, images, or fonts
A successful PDF response does not prove that Chrome could read every asset. Relative URLs, private routes, file:// references, CORS rules, and container paths can all produce an incomplete document.
Make assets reachable to the renderer
- Prefer absolute, renderer-reachable HTTP(S) URLs for assets served by your application.
- For private pages, provide the required authentication headers or cookies to the rendering context.
- Confirm DNS, TLS certificates, firewall rules, and service-to-service routing from the worker—not from your laptop.
- Use published storage URLs for uploaded files instead of paths that exist only on a developer workstation.
- Wait for the page or a specific selector before producing the PDF when styles or images load asynchronously.
When local files are intentional, customize Browsershot with Chrome options that allow local-file access. Spatie documents global and per-PDF customization, including the web-security option, at Customizing Browsershot. Disabling web security is a targeted diagnostic or controlled rendering setting, not a blanket production remedy; limit it to the rendering context that needs it.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #3
Prove whether the problem is HTML or storage
Render a minimal HTML document containing inline CSS and a plain text string. If that works, add the external stylesheet, image, and font one at a time. This identifies the first inaccessible resource instead of masking several failures behind one large view.
5. Isolate PDF output from Laravel delivery
Browsershot can save directly to a filesystem path, render supplied HTML, or return base64 PDF data. Use these modes to separate browser rendering from Laravel storage and HTTP response problems. The API examples are documented in Creating PDFs with Browsershot.
Save to a known writable path
use SpatieBrowsershotBrowsershot;
Browsershot::url('https://example.com')
->save('/absolute/path/to/output/example.pdf');
If this fails, inspect the browser, permissions, and temporary directory. If it succeeds, the remaining issue is likely Laravel’s filesystem disk, queue hand-off, or response code.
Render supplied HTML
Browsershot::html($html)
->savePdf('/absolute/path/to/output/example.pdf');
This removes routing, authentication, and application-view loading from the test. It is useful for deciding whether the browser can create a PDF from the markup itself.
Rank #4
Use base64 where files cannot be written
In serverless or restricted environments, obtain base64 PDF data and upload it to a permitted object store or return it through an appropriate response. Base64 avoids an unwritable local output path; it does not remove the need for Chrome, Node.js, temporary space, or reachable assets.
6. Handle timeouts, blank pages, and unstable pages
Timeouts
- Check the target URL directly from the worker network namespace.
- Reduce page work by deferring nonessential scripts and assets.
- Wait for a meaningful selector or network-idle condition instead of an arbitrary short delay.
- Give the browser enough temporary disk and memory; a process killed by the operating system can look like a generic generation failure.
Blank or partially rendered output
- Confirm the URL returns the expected status and content to an unauthenticated browser session.
- Check whether a login redirect, bot challenge, cookie banner, or consent modal covers the page.
- Capture a diagnostic screenshot or save the rendered HTML before PDF conversion when possible.
- Ensure client-side data has finished rendering before PDF output begins.
Fonts and print layout
Verify that font files are reachable and that the CSS includes print rules appropriate for PDF output. A browser PDF is paginated output, so fixed-height containers, overflowing flex layouts, and backgrounds disabled by print settings can produce apparently missing content even when the HTML is correct.
7. Choose another driver only for a stated constraint
Changing drivers changes dependencies; it does not automatically remove them. Laravel PDF’s documented alternatives include the Chrome driver, DOMPDF, Gotenberg, WeasyPrint, and Cloudflare Browser Run. Compare them against your actual HTML/CSS needs and deployment model.
| Driver family | Relevant requirement | When it may fit |
|---|---|---|
| Browsershot | Node.js plus Chrome/Chromium | Browser-level rendering with JavaScript support. |
| Chrome | Chrome/Chromium; no Node.js or Puppeteer | You want a browser driver but cannot include Node.js. The browser is still installed locally. |
| DOMPDF | PHP-based; no external browser binary | Deployment forbids external binaries and your markup fits its supported rendering model. |
| Gotenberg, WeasyPrint, Cloudflare Browser Run | Each has its own service, binary, or hosted-runtime requirements | You prefer a separate service or a different rendering stack. |
The Chrome driver documentation notes that it does not download or bundle a browser and that locked-down environments may require no_sandbox. Read Using the Laravel PDF Chrome driver before switching.
Best Value
8. A repeatable production checklist
- Log the exact exception and identify the failing stage.
- Run Node, npm, and Chrome checks as the real web or queue user.
- Set absolute executable, module, binary, and temporary paths where PATH differs.
- Confirm the Browsershot package is explicitly installed for Laravel PDF v2.
- Render minimal inline HTML, then add assets individually.
- Verify asset URLs, authentication, local-file access, and any required waiting condition.
- Save to a known writable path or use base64 to separate rendering from delivery.
- Inspect worker memory, disk, permissions, and restart long-running workers after deployment.
- Only then evaluate another driver against the specific dependency or fidelity constraint.
Or skip the browser setup
If your requirement is a dependable URL-to-PDF or screenshot endpoint rather than maintaining Chrome and Node.js inside Laravel, ScreenshotNeo provides a single API request. It can return PNG, JPEG, WebP, or PDF output and includes options such as full-page capture, waiting for selectors or network idle, custom headers and cookies, JavaScript, PDF page settings, and asynchronous jobs.
Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the complete parameter list and PDF options in the ScreenshotNeo documentation. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for the free ScreenshotNeo plan.
Frequently Asked Questions
Why does Browsershot work in my terminal but fail in a queue job?
The queue worker may have a different PATH, user, container, permissions, home directory, or temporary directory. Check Node.js and Chrome as the worker identity and configure absolute paths.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Does switching to Laravel PDF’s Chrome driver remove the browser dependency?
No. It removes the Node.js and Puppeteer requirement, but it still needs a locally installed Chrome or Chromium executable and may require no-sandbox configuration in locked-down environments.
What is the quickest way to tell whether storage or Chrome is failing?
Render minimal inline HTML to an absolute writable path with Browsershot. A successful file isolates the remaining problem to Laravel’s storage, queue hand-off, or HTTP response.
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.

