DEV Community

Cover image for Fixing Playwright build errors on Render when browsers are missing
Terry W
Terry W

Posted on • Edited on

Fixing Playwright build errors on Render when browsers are missing

Background

I use Playwright in my API to render email templates for my app, Snap Template.

It worked fine on my computer—insert “works on my machine” meme here—but after deploying to Render, the export feature failed because Playwright could not find the Chromium executable.

Render deploy log with Playwright executable not found error

The deployment itself completed successfully. The failure occurred at runtime when the API attempted to launch Chromium.

Root Cause

Locally, I had previously run:

npx playwright install
Enter fullscreen mode Exit fullscreen mode

That downloaded the browser binaries into Playwright’s cache on my computer.

The Render environment did not have the same local cache, so although the Playwright package was installed, the Chromium executable it expected was missing.

Playwright normally stores browsers in an operating-system-specific cache. On Linux, that defaults to:

~/.cache/ms-playwright
Enter fullscreen mode Exit fullscreen mode

The location can be changed using PLAYWRIGHT_BROWSERS_PATH.

The Fix That Worked

1. Install Chromium During postinstall

I added the following script to package.json:

{
  "scripts": {
    "postinstall": "playwright install chromium",
    "build": "your-build-command"
  }
}
Enter fullscreen mode Exit fullscreen mode

This installs only Chromium rather than downloading every browser supported by Playwright.

Because my API launches Playwright in production, the relevant Playwright package also needs to be inside dependencies, not only devDependencies:

{
  "dependencies": {
    "playwright": "your-installed-version"
  }
}
Enter fullscreen mode Exit fullscreen mode

Production dependencies are packages required for the deployed application to run, while development dependencies are intended for development and testing tools that are not needed at runtime.

2. Use a Render Build Command

My Render build command can now be:

npm ci && npm run build
Enter fullscreen mode Exit fullscreen mode

Or, when the project does not have a suitable lockfile:

npm install && npm run build
Enter fullscreen mode Exit fullscreen mode

There is no need to add npm run postinstall manually:

npm install && npm run postinstall && npm run build
Enter fullscreen mode Exit fullscreen mode

npm automatically runs lifecycle scripts such as postinstall as part of the installation process. Running it again would download or verify the browser installation twice.

Alternatively, you can remove the postinstall script and make the browser installation explicit:

npm ci && npx playwright install chromium && npm run build
Enter fullscreen mode Exit fullscreen mode

Either approach is valid. I used postinstall so the browser installation remains part of the dependency setup.

3. Configure the Browser Path

In Render, I added:

PLAYWRIGHT_BROWSERS_PATH=/opt/render/project/.cache/playwright
Enter fullscreen mode Exit fullscreen mode

Render environment variables page showing PLAYWRIGHT\_BROWSERS\_PATH set

The important part is not that every host must use this exact path. The important part is that the same PLAYWRIGHT_BROWSERS_PATH value is available during both:

  • Browser installation
  • Application runtime

This tells Playwright where to install Chromium and where to look for it later. Playwright officially supports overriding its default browser cache with this environment variable.

For a more portable project-local installation, Playwright also supports:

PLAYWRIGHT_BROWSERS_PATH=0
Enter fullscreen mode Exit fullscreen mode

This stores the browsers under:

node_modules/playwright-core/.local-browsers
Enter fullscreen mode Exit fullscreen mode

That is known as a hermetic installation.

Why It Works

The corrected deployment flow is:

  1. Render installs the project dependencies.
  2. npm automatically runs postinstall.
  3. Playwright downloads the Chromium version expected by the installed package.
  4. Chromium is stored at the configured browser path.
  5. The API starts with the same environment variable.
  6. Playwright finds and launches the installed executable.

package.json scripts section showing postinstall entry

Render deploy log showing successful deploy and export run

Missing Browser vs Missing System Libraries

This fix addresses a missing Chromium executable.

If the error changes to missing shared libraries or operating-system dependencies, the browser is installed but the environment does not contain everything required to launch it.

Playwright can install browser dependencies using:

npx playwright install --with-deps chromium
Enter fullscreen mode Exit fullscreen mode

However, installing system packages may require permissions that are not available in every managed hosting environment. Playwright documents --with-deps as the combined browser and operating-system dependency installation command.

When native deployment does not provide the required libraries, Docker gives you more control over the runtime environment.

Using Docker Instead

For more reproducible deployments, Playwright provides Docker images containing browser binaries and required system dependencies.

Pin the image to the Playwright version used by your project:

FROM mcr.microsoft.com/playwright:vX.Y.Z-noble
Enter fullscreen mode Exit fullscreen mode

Replace vX.Y.Z with the version matching your installed Playwright package.

Avoid using:

FROM mcr.microsoft.com/playwright:latest
Enter fullscreen mode Exit fullscreen mode

A version mismatch can mean the container has different browser binaries from those expected by the package.

The Playwright Docker image contains browsers and operating-system dependencies, but your application still needs to install its npm dependencies.

Extra Checks and Good Practices

Check the Installed Playwright Version

npx playwright --version
Enter fullscreen mode Exit fullscreen mode

Each Playwright release expects specific browser versions, so reinstall the browsers after upgrading Playwright.

Log the Resolved Executable Path

A temporary debug log can confirm where Playwright expects Chromium:

import { chromium } from "playwright";

console.log(
  "Chromium executable:",
  chromium.executablePath()
);
Enter fullscreen mode Exit fullscreen mode

Remove or reduce diagnostic logging once the deployment is stable.

Check the Installed Browsers

npx playwright install --list
Enter fullscreen mode Exit fullscreen mode

This can help confirm whether Chromium was installed and where Playwright found it.

Monitor Disk Usage

Playwright browser installations can consume hundreds of megabytes, so monitor the service’s storage and build logs.

Install Only What You Need

Installing Chromium directly is already enough to avoid downloading Firefox and WebKit:

npx playwright install chromium
Enter fullscreen mode Exit fullscreen mode

For strictly headless workloads, Playwright also provides an --only-shell option that can avoid downloading the full Chromium browser:

npx playwright install --only-shell chromium
Enter fullscreen mode Exit fullscreen mode

Whether that option is appropriate depends on how your application launches and uses Chromium.

Install During Build, Not on Request

Do not download Chromium when a user requests an export.

Installing during runtime would:

  • Increase response and cold-start time
  • Add an external network dependency to the request
  • Risk concurrent downloads
  • Make failures harder to diagnose

Install the browser during the deployment build instead.

Checklist

  • Is Playwright in dependencies when it is used by the production API?
  • Did postinstall run during the Render build?
  • Did the build log show Chromium being downloaded?
  • Is PLAYWRIGHT_BROWSERS_PATH available during both build and runtime?
  • Does chromium.executablePath() point to an existing file?
  • Does the Playwright package version match the installed browser?
  • If Chromium exists, are Linux system libraries missing instead?
  • Would a pinned Playwright Docker image provide a more reliable environment?

Closing Notes

If Playwright works locally but fails after deployment, remember that the npm package and browser binaries are separate.

My local machine already had Chromium inside Playwright’s cache, while the Render service did not. Installing Chromium during the build and configuring a consistent PLAYWRIGHT_BROWSERS_PATH solved the runtime error for Snap Template.

The final setup was:

{
  "scripts": {
    "postinstall": "playwright install chromium"
  }
}
Enter fullscreen mode Exit fullscreen mode
npm ci && npm run build
Enter fullscreen mode Exit fullscreen mode
PLAYWRIGHT_BROWSERS_PATH=/opt/render/project/.cache/playwright
Enter fullscreen mode Exit fullscreen mode

If this helped you do the Playw-right thing and get your service running, share what deployment setup worked for you.

TL;DR

If Playwright works locally but fails on Render with an executable does not exist error:

  1. Install Chromium during the build.
  2. Configure PLAYWRIGHT_BROWSERS_PATH so installation and runtime use the same location.
  3. Make sure Playwright is installed as a production dependency.
  4. Avoid running the postinstall script twice.

Playwright requires browser binaries that match the installed Playwright version. Installing the npm package alone does not guarantee that Chromium is available in the deployed environment.

Top comments (0)