ScreenshotNeo

BlogHow-to

Why ChromeDriver Stops Responding on CentOS 7 and How to Fix It

Diagnose ChromeDriver hangs on CentOS 7 by checking versions, startup logs, user privileges, browser dependencies, and the platform’s end-of-life status.

By the ScreenshotNeo team1 October 202610 min read

Short answer: “ChromeDriver stopped responding” is a symptom, not a diagnosis. First capture the exact Selenium exception and ChromeDriver log, then record the Chrome and ChromeDriver versions and the actual Chrome binary being launched. Match the driver to that browser, launch the same binary outside WebDriver under the same account, and remove root execution from the job. CentOS Linux 7 reached end of life on June 30, 2024, so migration to a maintained operating system is the durable platform fix, although it does not replace the version and startup checks.

This guide separates session-creation failures, Chrome startup crashes, permission problems, and test-harness failures. It also shows a repeatable Selenium setup and a hosted screenshot alternative when maintaining a CentOS browser stack is unnecessary.

1. Identify where the failure occurs

Use the exception text and log timing to classify the failure:

Observed symptom Likely area First evidence to collect
session not created with a version message Chrome and ChromeDriver incompatibility Both version outputs and the driver-selection rule used
Driver starts, then Chrome exits immediately Browser startup, account, sandbox, dependencies, or flags ChromeDriver log and direct launch of the exact binary
Request hangs until Selenium timeout Chrome process, display/headless setup, page load, or service environment Process list, driver log, page-load timeout, and service account
Works in a shell but fails from cron/systemd/CI Different PATH, HOME, permissions, environment, or user Environment and executable path from the job itself

Do not update packages blindly before saving this evidence. A compatibility error needs a different fix from a Chrome process that crashes before a session is created.

2. Capture versions and the complete log

Run these commands as the same account that runs Selenium. Replace paths when your installation uses a nonstandard location.

# Record the driver version
chromedriver --version

# Find the browser and record its version
command -v google-chrome || command -v google-chrome-stable || command -v chromium
/usr/bin/google-chrome --version

# Check the account and environment used by the job
id
printf 'PATH=%s\nHOME=%s\nDISPLAY=%s\n' "$PATH" "$HOME" "$DISPLAY"

# Confirm the process and executable paths while a job is running
ps -ef | grep -E '[c]hrome|[c]hromedriver'

ChromeDriver’s startup guidance recommends checking the binary named in its log. A service can resolve a different executable than your interactive shell, so inspect the log rather than assuming command -v is the binary under test. Save the full Selenium exception and start ChromeDriver with verbose logging if your binding supports it.

3. Match ChromeDriver to the installed Chrome

Driver selection changed with Chrome 115. For Chrome 115 and newer, the ChromeDriver release process is integrated with Chrome: use a correspondingly versioned Chrome for Testing browser and driver, or the documented JSON endpoints for the matching build. For Chrome 114 and older, follow ChromeDriver’s version-selection guidance and match the documented major, minor, and build numbers. See ChromeDriver version selection.

Do not rely on a generic “latest driver” instruction. A legacy Selenium driver manager may still query the pre-115 endpoint and select incorrectly. Verify that its selection logic understands the Chrome 115 release-process change. The ChromeDriver downloads documentation is useful for locating the appropriate release artifacts.

Compatibility checklist

  • Record the exact Chrome executable path from the ChromeDriver log.
  • Record that executable’s version, not only the browser version shown in a desktop menu.
  • Record chromedriver --version from the job’s PATH or use an absolute path.
  • Check the matching rule for the browser generation: Chrome 115+ versus 114 and older.
  • Restart the service after replacing the driver so an old process is not reused.

4. Launch Chrome without WebDriver

ChromeDriver’s isolation procedure is simple: launch the exact browser binary directly, under the exact account used by the automation, with the switches your test supplies. If Chrome fails here, WebDriver is not the primary fault; repair or reinstall the browser or its runtime dependencies. If direct launch works but WebDriver fails, inspect the service account, environment, permissions, and arguments.

# Use a writable profile so the test does not touch a real user profile
mkdir -p /tmp/chrome-cd-check
/usr/bin/google-chrome \
  --headless \
  --disable-gpu \
  --user-data-dir=/tmp/chrome-cd-check \
  https://example.com

Use the same headless mode and other switches as the test. A successful command should leave a Chrome process long enough to load the page and should not immediately print a missing-library or permission error. Remove the temporary profile after diagnosis.

5. Run Selenium with explicit paths and safe defaults

The following Python example makes the browser binary, driver path, headless mode, profile directory, and timeouts visible. It is intended for diagnosis; adapt the paths to your host.

#!/usr/bin/env python3
import os
import tempfile
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service

chrome_binary = os.environ.get("CHROME_BINARY", "/usr/bin/google-chrome")
chromedriver_binary = os.environ.get("CHROMEDRIVER_BINARY", "/usr/local/bin/chromedriver")

options = Options()
options.binary_location = chrome_binary
options.add_argument("--headless")
options.add_argument("--disable-gpu")
options.add_argument("--window-size=1365,900")
# A dedicated writable profile avoids collisions between parallel jobs.
profile = tempfile.mkdtemp(prefix="selenium-chrome-")
options.add_argument(f"--user-data-dir={profile}")

service = Service(executable_path=chromedriver_binary, log_output="chromedriver.log")
driver = None
try:
    driver = webdriver.Chrome(service=service, options=options)
    driver.set_page_load_timeout(60)
    driver.get("https://example.com")
    print(driver.title)
finally:
    if driver is not None:
        driver.quit()

Run it as a normal service user, not root. If the script fails, inspect chromedriver.log and the browser’s stderr output. Keep the explicit paths while diagnosing; once stable, you can move them into deployment configuration.

6. Check account, sandbox, and filesystem permissions

Running Chrome as root is a documented common cause of startup crashes on Linux. Change the systemd unit, cron entry, container command, or CI runner to a regular user with a writable home directory, temporary directory, and browser profile.

ChromeDriver documentation says that passing --no-sandbox can work around root execution, but that configuration is unsupported and highly discouraged. Treat it as a sign that the job’s account model needs correction, not as a general fix.

# Example service-account checks
id
ls -ld "$HOME" /tmp
mkdir -p "$HOME/.cache" "$HOME/.config"
touch "$HOME/.cache/chrome-write-test"

Also check for profile collisions. Two concurrent Chrome processes sharing one --user-data-dir can block each other or corrupt the profile. Give every job a unique directory and remove stale lock files only after confirming that no Chrome process still owns the profile.

7. Treat CentOS 7’s end of life as a platform problem

The CentOS Project lists June 30, 2024 as the end-of-life date for CentOS Linux 7. Updates stopped after that date and packages were archived. Continuing to run a browser automation stack there increases the chance of unsupported browser, runtime, and security combinations. Plan migration to a maintained operating system, then repeat the same version and startup diagnostics on the new host. The CentOS end-date announcement and CentOS comparison page provide the project’s platform context.

Migration alone does not prove the cause of a particular hang. Preserve the old Chrome version, driver version, Selenium version, and logs while validating the new environment so that you can distinguish an OS change from a compatibility change.

8. Interpret glibc and package errors carefully

A 2021 CentOS mailing-list discussion reported a Chrome 95 package dependency on GLIBC_2.18 that prevented installation on one CentOS 7 setup. Later posts in that same thread said subsequent Google-repository beta and stable packages no longer showed the dependency error. This is historical community evidence, not a current compatibility guarantee and not proof that glibc causes every “stops responding” incident. Read the dated discussion at the CentOS mailing list.

If installation output names a missing GLIBC symbol, record the exact package build and dependency text. Prefer a supported browser/runtime combination or OS migration. Do not replace the system glibc in place as a casual repair; that can destabilize unrelated software.

9. Configuration choices that affect reliability

Setting Use it when Risk or note
Explicit binary_location Multiple Chrome installations or service PATH differences exist Keep the path in deployment configuration and verify it in logs
Dedicated user-data-dir Jobs run concurrently or the service account has no normal profile Use a unique writable directory per job
Headless mode No display server is available Use the same mode during direct-launch testing; do not infer display problems from a version error
Page-load timeout Pages can legitimately be slow A timeout after Chrome starts is different from a startup crash
Service account Running from systemd, cron, or CI Compare its PATH, HOME, permissions, and environment with an interactive shell

10. Troubleshooting common errors

SessionNotCreatedException: This version of ChromeDriver only supports Chrome version ...

Cause: The driver does not match the installed browser according to the applicable release-generation rules.
Fix: Record both versions, identify whether Chrome is 115+ or 114 and older, obtain the corresponding driver, and restart the service.

DevToolsActivePort file doesn't exist or Chrome exits immediately

Cause: Chrome failed during startup. Common areas are root execution, an unwritable profile, an invalid binary path, missing libraries, or conflicting flags.
Fix: Launch the exact binary directly under the job account, use a new writable profile, inspect ChromeDriver logs, and remove root execution.

The job works over SSH but hangs in cron or systemd

Cause: The service has a different PATH, HOME, DISPLAY, working directory, or user.
Fix: Log those values from the job, set absolute browser and driver paths, create writable directories, and use headless mode when no display is available.

Chrome installs but reports a GLIBC symbol error

Cause: The particular package build requires a runtime symbol unavailable on the host.
Fix: Preserve the exact dependency output, select a supported package/runtime combination, or migrate the OS. Do not generalize from the 2021 mailing-list report.

Only parallel jobs fail

Cause: Shared profiles, ports, temporary files, or resource exhaustion.
Fix: Allocate a unique profile and temporary directory per process, cap concurrency, and inspect process and memory usage.

Chrome loads but Selenium times out on a page

Cause: This is likely page loading, network access, authentication, or an overly short timeout rather than ChromeDriver startup.
Fix: Verify the URL from the same host, set an appropriate page-load timeout, and capture the browser and driver logs separately.

11. Performance, reliability, and operating cost

  • Startup cost: Creating a fresh Chrome process and profile for every URL is slower than reusing a controlled session, but reuse requires strict cleanup and isolation.
  • Concurrency: Increase workers only after measuring memory, CPU, temporary storage, and file-descriptor use. CentOS 7’s age makes resource and package limits more likely to become operational constraints.
  • Reliability: Pin a tested browser/driver pair, log exact versions, use a dedicated service user, and fail fast when the binary cannot launch.
  • Observability: Keep ChromeDriver logs with the Selenium exception and job metadata. A timeout without the driver log is difficult to distinguish from a page-load failure.
  • Cost: Self-hosting consumes maintenance time for browser updates, driver matching, OS migration, and incident response. Compare that operational work with a screenshot API when you only need rendered images or PDFs.

12. A repeatable repair checklist

  1. Save the complete exception and ChromeDriver log.
  2. Record the actual Chrome binary path and both version outputs.
  3. Apply the Chrome 115+ or 114-and-older selection workflow.
  4. Launch that binary directly under the automation account.
  5. Remove root execution and avoid --no-sandbox as a permanent workaround.
  6. Use explicit paths, a writable unique profile, and matching headless settings.
  7. Check package output for missing libraries, including any GLIBC symbol named in the error.
  8. Plan migration away from CentOS Linux 7 and retest with the same evidence.

Or skip the browser setup

If your goal is a rendered screenshot or PDF rather than maintaining Selenium on an end-of-life host, ScreenshotNeo provides a GET endpoint that returns PNG, JPEG, WebP, or PDF. Its pre-capture flow accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and each response reports the result with X-Page-Verdict and X-Billed headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

See the ScreenshotNeo API documentation for the complete option list.

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

ScreenshotNeo includes full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and margin controls, custom CSS and JavaScript, clicks and waits, request blocking, custom headers and cookies, timezone and geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. Every feature is on every plan. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

FAQ

Is CentOS 7 itself guaranteed to be incompatible with ChromeDriver?

No. The title alone cannot establish the cause. Use the browser/driver versions, startup log, account, and package output to identify the failing layer.

Should I always add --no-sandbox?

No. ChromeDriver documents root execution as a common startup-crash cause and describes --no-sandbox as unsupported and highly discouraged. Run the job as a regular user instead.

Does upgrading Selenium fix a driver mismatch?

Not necessarily. The installed Chrome and ChromeDriver still need to be selected as a compatible pair using the correct Chrome release-generation workflow.

What should I preserve before migrating off CentOS 7?

Save the exact browser and driver versions, Selenium configuration, service environment, complete logs, and any dependency errors. Reproduce the checks after migration.