pip install playwright gives you the library. It does not give you a browser. That is what python -m playwright install chromium is for, and it is the step that trips people up, because it fails in ways that look like Playwright is broken when it is only missing a download. This guide explains what the command does, where the files go, how to run it in Docker and CI, and how to fix the errors you will actually see.
What the command does
pip install playwright
python -m playwright install chromium
The second line downloads a specific build of Chromium, the one your installed Playwright version was tested against, into a cache folder on your machine. Playwright does not use whatever Chrome you already have installed. It ships its own, pinned build, so that the version of the browser and the version of the automation protocol always match. That is why upgrading the Python package later requires a fresh install: the new package expects a new build.
python -m playwright install chromium and playwright install chromium are the same command. The python -m form works even when the script directory is not on your PATH, which is the usual situation inside a virtual environment that has not been activated, in cron jobs, and in some containers. If playwright alone gives "command not found", use the python -m form rather than fixing PATH.
Without an argument, playwright install downloads all three engines: Chromium, Firefox and WebKit. That is several hundred megabytes you probably do not need. Name the browser. Recent Playwright versions also ship a slimmer chromium-headless-shell build for headless runs; install chromium fetches it alongside the full browser, and you can install just the shell if you never need a visible window.
Where the browser goes
| Platform | Default cache location |
|---|---|
| Linux | ~/.cache/ms-playwright |
| macOS | ~/Library/Caches/ms-playwright |
| Windows | %USERPROFILE%\AppData\Local\ms-playwright |
Inside that folder each browser sits in a versioned directory, something like chromium-1140/chrome-linux/chrome. The number is Playwright's internal build revision, not the Chrome version. The cache is per user: if you install as one user and run the script as another (a very common Docker and systemd mistake), the second user cannot see the download and you get the executable-not-found error below.
To put the browsers somewhere else, set PLAYWRIGHT_BROWSERS_PATH before both the install and the run:
export PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers
python -m playwright install chromium
The special value PLAYWRIGHT_BROWSERS_PATH=0 installs the browser inside the Playwright package directory itself, which makes the whole thing portable with the virtual environment. It is useful when you want to bundle a scraper as a single deployable folder.
Linux servers: the dependency problem
On a desktop the browser runs after the download. On a bare Linux server it often does not, because Chromium needs a long list of shared libraries (fonts, graphics, audio stubs) that a minimal server image does not carry. The error names them: "Host system is missing dependencies to run browsers." Two fixes, both needing root:
python -m playwright install --with-deps chromium
# or, separately
python -m playwright install-deps chromium
install-deps calls the system package manager for you. It supports Debian and Ubuntu well; on other distributions you may need to install the listed packages by hand. If you cannot get root, the Docker route below is the cleaner answer.
Docker and CI
Microsoft publishes images with the browsers and every dependency preinstalled. Match the image tag to your Playwright version exactly, or you are back to a version mismatch:
FROM mcr.microsoft.com/playwright/python:v1.47.0-noble
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt # pin playwright==1.47.0 here too
If you build on a plain Python image instead, run install --with-deps chromium in the Dockerfile, and do it as the same user that will run the container, for the reason above.
In CI, cache the browser directory between runs and key the cache on the Playwright version. A fresh download on every job is slow and, on a bad day, the reason the pipeline fails. Downloading through a corporate proxy works if HTTPS_PROXY is set in the environment where the install runs.
The errors and what they mean
Executable doesn't exist at .../chromium-XXXX/chrome-linux/chrome
Playwright is looking for a specific revision and it is not there. Causes, in order of likelihood: you upgraded Playwright and did not reinstall the browser; the browser was installed as a different user; PLAYWRIGHT_BROWSERS_PATH was set during install but not at run time, or the other way round. The fix is the same in every case: run python -m playwright install chromium in the exact environment, user and shell that runs your script.
Host system is missing dependencies to run browsers
Linux shared libraries are missing. Use --with-deps or install-deps as above, or move to the official Docker image.
Download failed, or the install hangs
Usually a network restriction. Set HTTPS_PROXY, or use PLAYWRIGHT_DOWNLOAD_HOST to point at an internal mirror if your organisation runs one. A partially downloaded browser can also leave a broken folder behind; delete the versioned directory in the cache and run the install again.
BrowserType.launch: Target page, context or browser has been closed
Not an install problem, but people hit it right after installing. Inside containers it is normally a sandbox issue; launch with args=["--no-sandbox"] or run as a non-root user with the proper capabilities. If it appears only under load, you are out of memory or shared memory (/dev/shm) and need to raise the container's shm_size.
A quick check that it worked
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://spyderproxy.com/tools/ip-lookup")
print(page.title())
browser.close()
If that prints a title, the install is correct and every later problem is a scraping problem, not a setup one.
Adding a proxy once the browser runs
Installing the browser and routing its traffic are separate concerns. Playwright takes a proxy at launch or per context:
browser = p.chromium.launch(proxy={
"server": "http://gate.example.com:12321",
"username": "USER",
"password": "PASS",
})
One Chromium limitation to know about: it supports SOCKS5 proxies but not SOCKS5 authentication, so with Chromium use an HTTP(S) proxy endpoint when your provider requires a username and password, and keep SOCKS5 for Firefox or for unauthenticated setups. For the scraping side of Playwright, waiting for dynamic content, extracting data and avoiding detection, see Playwright web scraping in Python and the broader headless browser guide. A working install with a datacenter IP is fine for testing; for anything that checks reputation, put a residential proxy in that launch call.
Frequently asked questions
Do I need to run playwright install after pip install playwright?
Yes. pip installs the Python package and the command-line tool; it does not include a browser. Run playwright install chromium (or python -m playwright install chromium) to download the Chromium build that matches your installed Playwright version. You need to run it again every time you upgrade Playwright.
Where does Playwright install Chromium?
Into a per-user cache: ~/.cache/ms-playwright on Linux, ~/Library/Caches/ms-playwright on macOS, and %USERPROFILE%\AppData\Local\ms-playwright on Windows. Set the PLAYWRIGHT_BROWSERS_PATH environment variable to change it, both when installing and when running.
Why does Playwright say the executable does not exist?
Almost always because the Playwright package was upgraded but the browsers were not. Each Playwright version pins a specific Chromium build and looks for it in a versioned folder. Run playwright install chromium again under the same user and environment that runs your script.
What is the difference between playwright install and playwright install --with-deps?
install downloads the browser binaries only. --with-deps also installs the operating system libraries the browser needs, which is a Linux concern; it requires root. On a server that fails with a missing dependencies error, --with-deps or a separate playwright install-deps is the fix.
Does playwright install chromium work behind a proxy?
Yes. The downloader honours the HTTPS_PROXY environment variable, so set it before running the command on a locked-down network. That is for downloading the browser; routing your scraping traffic through a proxy is configured separately when you launch the browser or create a context.