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.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Fix the error by making a browser and its matching driver available inside the final Alpine container, then verify them there. For Chromium, install Alpine’s chromium and chromium-chromedriver packages from the same repository branch and architecture, confirm both commands work, and either let Selenium Manager resolve the driver or pass the verified absolute path through the browser’s Service object. If the driver is found but immediately exits, you have a browser-startup or compatibility problem rather than a discovery problem.

First identify which failure you have

Selenium needs a browser-specific WebDriver executable, such as chromedriver for Chrome or Chromium. The Selenium Project’s Unable to Locate Driver Error guide distinguishes a driver that cannot be found from one that was found but failed to start.

  • Discovery failure: messages such as “Unable to locate the chromedriver executable,” “The file geckodriver does not exist,” or a notice that the driver must be in PATH.
  • Startup failure: Selenium launches a driver process, but it exits unexpectedly, cannot connect to the browser, or reports a browser/driver incompatibility.

Save the complete exception and driver log before changing the image. A missing-path error calls for the steps below; a process-exit error requires the compatibility and runtime checks in the later section.

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

Install Chromium and chromedriver as a matched Alpine pair

Alpine’s chromium-chromedriver package provides the chromedriver command and depends on Chromium. Install both from the same Alpine branch and CPU architecture so Alpine’s package metadata keeps their relationship coherent. The package names are stable, but versions vary by release and architecture. For example, the Alpine v3.23 community x86_64 metadata showed 149.0.7827.53-r0 when observed in 2026; do not copy that version into a generic Dockerfile.

FROM alpine:3.23

RUN apk add --no-cache chromium chromium-chromedriver

# Optional diagnostics during image construction
RUN command -v chromium && 
    command -v chromedriver && 
    chromium --version && 
    chromedriver --version

WORKDIR /app
COPY . .
CMD ["python3", "run_tests.py"]

Check the exact package availability for your target branch and platform in Alpine’s chromium-chromedriver package index and the corresponding Chromium package metadata. A Docker build that mixes repositories, branches, or architectures can install binaries that do not belong together.

Verify the final container, not the build host

Docker runs your test under the final image, user, environment variables, and PATH. A successful check on your laptop or an earlier build stage does not prove that the runtime container can execute the driver.

docker run --rm -it your-image:tag sh

command -v chromium
command -v chromedriver
chromium --version
chromedriver --version
printf '%sn' "$PATH"
ls -l "$(command -v chromedriver)"
  • If command -v chromedriver prints nothing, inspect the installed package with apk info -e chromium-chromedriver and correct PATH or the image layer.
  • If it prints a path but chromedriver --version fails, check execute permission, shared libraries, and CPU architecture.
  • Run these commands as the same non-root user that starts Selenium; a different user can have a different PATH or filesystem access.

Choose Selenium Manager or an explicit driver path

Use Selenium Manager when its conditions are met

Selenium Manager is included with Selenium releases as of 4.6 and is used as a fallback when you have not supplied a driver. The Selenium documentation states: “As of Selenium 4.6, Selenium downloads the correct driver for you.” Upgrade the language binding if you are on an older release, then enable Selenium Manager logging when resolution fails. Automatic management still depends on the browser being present and on the container permitting the required downloads and cache writes; it is not a guarantee for every restricted Alpine environment. The Selenium client API documentation is available at selenium.dev/selenium/docs/api/py/.

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

For a reproducible, offline-friendly image, installing Alpine’s packages and passing their verified path is usually easier to diagnose than relying on a first-run download.

Pass an absolute path with the browser Service object

Do not guess Alpine paths. Obtain them with command -v, then use the browser-specific Service class. This Python example assumes those commands returned /usr/bin/chromium and /usr/bin/chromedriver; substitute the actual paths from your image.

from selenium import webdriver
from selenium.webdriver.chrome.service import Service

options = webdriver.ChromeOptions()
options.binary_location = "/usr/bin/chromium"  # Verify in the image.
service = Service(executable_path="/usr/bin/chromedriver")

driver = webdriver.Chrome(service=service, options=options)
try:
    driver.get("https://example.com")
    print(driver.title)
finally:
    driver.quit()

For Firefox, use the Firefox binding and its Service class with the actual geckodriver path. Other Selenium languages expose the same concept through their browser-specific service options. Selenium’s guide documents an explicit Service path as an alternative to environment-variable discovery.

Make Alpine browser startup reliable

Use container-appropriate Chrome options

In a container without a desktop session, Chromium normally needs headless operation. Add the options your security model requires rather than copying flags indiscriminately:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
options = webdriver.ChromeOptions()
options.binary_location = "/usr/bin/chromium"
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")

--no-sandbox reduces isolation and should be avoided when you can run Chromium with a functioning sandbox and an appropriate user. --disable-dev-shm-usage can help when Docker’s shared-memory mount is too small, but increasing /dev/shm is preferable for heavy pages when your deployment permits it.

Check version, architecture, and libraries

  • Compare chromium --version and chromedriver --version; a driver from another release line may reject the browser.
  • Confirm the image architecture with uname -m and ensure both packages and any downloaded binary target it.
  • Inspect missing dynamic libraries with Alpine tools such as ldd "$(command -v chromedriver)" when the executable starts and exits immediately.
  • Ensure the browser binary configured in binary_location actually exists and is executable.
  • Check that the runtime user can read the browser files, execute the driver, and write Selenium’s temporary and cache directories.

The SeleniumHQ docker-selenium project documents browser and driver availability by architecture and cautions against AMD64 emulation on ARM64 because of performance and stability concerns.

Diagnostic decision table

Symptom Likely layer Next check
“Unable to locate chromedriver” Discovery command -v chromedriver, package installation, and PATH
Driver path resolves, version command fails Executable/runtime Permissions, architecture, and shared libraries
Driver starts then exits Browser startup Browser path, headless flags, libraries, user, and logs
Session not created; version mismatch Compatibility Install browser and driver from the same Alpine branch and architecture
Manager cannot download a driver Network/cache Selenium version, outbound access, writable cache, and Manager logs

Common fixes when the first attempt fails

The package is installed but Selenium still says it is missing

Enter the running container and print PATH as the test user. If the driver is outside that path, use its absolute location in Service rather than exporting a path only in a Docker build layer. Also check that a later multi-stage COPY did not omit the package layer.

The image works on x86_64 but fails on ARM64

Rebuild for the target platform and use packages available for that architecture. Do not copy an x86_64 driver into an ARM64 image. If maintaining this matrix is impractical, evaluate a fully tagged official Selenium image and verify that the selected tag supports your architecture.

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

Selenium Manager works locally but not in CI

CI may block outbound downloads, run as a read-only user, or use a different cache directory. Capture Manager logs, verify network policy, and either provide a writable cache or bake the browser and driver into the image with apk add.

The browser opens manually but not through Selenium

Run the browser command as the same user, with the same headless flags and environment. A manual root shell can hide permission, sandbox, or display-server problems. Set binary_location only after confirming the path in the final image.

Remote Grid is involved

If your test connects to a remote Selenium Grid, the driver and browser must exist on the node that creates the session, not necessarily in the client container. Inspect the Grid node image and architecture before changing the client’s PATH.

When a maintained Selenium image is the better choice

A custom Alpine stack gives you a small base and direct package control, but you own browser updates, driver compatibility, architecture variants, libraries, and diagnostics. The official Selenium Docker project provides maintained images and documents supported combinations. If repeated environment mismatch is consuming more time than the image savings, choose a fully tagged image rather than an unpinned latest-style reference, and confirm current architecture support before deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a static page image rather than interactive Selenium automation, ScreenshotNeo makes one HTTP request and returns PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result.

Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Features include full-page lazy-image capture, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data, and an OpenAPI specification.

One-call example (see the ScreenshotNeo documentation for all parameters):

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The same request in 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)

And 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}`);

ScreenshotNeo includes 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

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.

FAQ

Do I need to download chromedriver manually?

No. Selenium Manager can manage a driver in Selenium 4.6 and newer when its browser, network, and cache conditions work. Alpine’s matching packages are a predictable alternative.

Is /usr/bin/chromedriver guaranteed?

No. Treat it as an example and verify the location with command -v chromedriver inside your exact image.

What details should I include when asking for help?

Provide the Selenium language and version, browser, Alpine release, CPU architecture, Dockerfile, complete exception, and whether the browser runs locally or on a remote Grid.

Frequently Asked Questions

Can I solve this only by adding chromedriver to PATH?

Only when the binary is already executable and compatible with the browser. If it starts and exits, investigate startup, libraries, architecture, and versions instead.

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

Should I pin an Alpine package version in the Dockerfile?

Use the versions available for your target Alpine branch and architecture; the package metadata changes, so verify availability before pinning.

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.