Yes—Selenium can drive Chrome on an Ubuntu server with no desktop session. Run Chrome in headless mode by adding --headless=new to the binding’s Chrome options, let Selenium Manager resolve a compatible driver when your Selenium version supports it, and always call quit() in teardown. The exact Chrome package, Ubuntu release, and Selenium binding determine the remaining setup, so verify those versions on the host rather than copying an unqualified package list.
What you need on a GUI-less Ubuntu host
A headless WebDriver session still needs a real Chrome (or Chromium) executable, its matching automation driver, the Selenium language binding, and the Linux libraries required by that browser build. “Headless” removes the visible window; it does not remove the browser process or its operating-system dependencies.
- An Ubuntu server image and a Chrome-family browser installed for that image.
- A current Selenium binding for your programming language.
- Network access during setup if Selenium Manager must download a driver, unless the driver is already cached or supplied by your deployment.
- Enough CPU, memory, temporary disk space, and permission for the account running the service.
Selenium’s published support is primarily tested on Ubuntu. Other Linux distributions and unusual Chrome builds may work, but vendor support and system-library requirements vary. Confirm the browser’s own installation guidance for your specific Ubuntu release and Chrome version; there is no single dependency command that is valid for every combination.
Run Chrome headless with Selenium
Python example
Install the Python binding in the environment used by your service, then create a Chrome options object and add the modern headless flag. Older convenience methods for headless mode were deprecated and removed in Selenium 4.10, so avoid examples that call a removed setter.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1365,900")
# Selenium Manager resolves ChromeDriver automatically in current bindings.
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com")
print(driver.title)
print(driver.current_url)
finally:
driver.quit()
The try/finally block matters on a server: it closes the browser and ends the WebDriver session even when navigation or an assertion fails. close() closes one window; quit() terminates the entire session and removes its associated resources.
Other language bindings
The same idea applies in Java, JavaScript, Ruby, C#, and other bindings: instantiate the binding’s Chrome options object, add the argument --headless=new, pass the options to the Chrome driver, and call the binding’s quit method in a guaranteed teardown path. Keep the browser and driver creation on the server; a local session runs on that machine, not on your laptop.
How ChromeDriver is obtained and matched
Start with Selenium Manager
Current Selenium bindings can delegate driver management to Selenium Manager. It inspects the installed browser, resolves a suitable ChromeDriver, downloads it when needed, and stores it in a local cache. This is the simplest setup for a single host or a development machine, provided the host can reach the download metadata and driver endpoint during provisioning.
A successful download is not proof that Chrome itself can launch. Selenium Manager handles driver resolution; it does not guarantee that the Ubuntu image contains every shared library, sandbox capability, font, or graphics-related dependency required by your particular browser package.
Pin versions when reproducibility matters
For production, record the exact Ubuntu image, Chrome version, Selenium binding version, and ChromeDriver version used in a release. Chrome and ChromeDriver distribution changed around browser versions 114 and 115, and the available metadata is a moving target. Check the current Chrome for Testing metadata and your browser vendor’s compatibility guidance at deployment time.
Pinning gives you a repeatable image and avoids an unexpected driver download after a browser update, but it creates an update job: test a new browser/driver pair together, roll it out deliberately, and keep a rollback image. Automatic management reduces maintenance but depends on network access and current resolver behavior.
Rank #3
| Approach | Advantages | Trade-offs |
|---|---|---|
| Selenium Manager | Minimal configuration; checks versions and caches a resolved driver. | Initial setup may require network access; a newly updated browser can change the resolved pair. |
| Explicit pinned browser and driver | Reproducible deployments and controlled upgrades. | You must maintain the browser image, driver binary, and compatibility checks. |
Validate the host before debugging Selenium
- Record the Ubuntu release and the account that will run the job.
- Record the browser’s reported version and executable path. Do not assume that a package called “Chrome” is present simply because a driver was downloaded.
- Use the same account and environment as the service to launch the browser. Differences in
PATH, home directory, permissions, temporary directories, and proxy variables commonly explain “works over SSH, fails in the service” behavior. - Run a minimal headless navigation to a page you control or a stable test URL, print the title, and then quit.
- Only after that test passes, add waits, cookies, custom profiles, downloads, or parallel workers.
If your server image is hardened, verify that the browser is allowed to start with its required sandbox and shared-memory behavior. Do not blindly add security-disabling flags; change them only when your deployment’s security policy and browser documentation justify it.
Waiting, page readiness, and cleanup
Headless execution changes display, not page timing. Use explicit waits for a selector that proves the page is ready instead of relying on a fixed sleep. A navigation can return before JavaScript-rendered content appears, while a long arbitrary delay wastes server capacity.
Keep one driver per test or job unless your framework explicitly supports safe reuse. Always quit on success, assertion failure, timeout, and cancellation. For long-running workers, monitor orphaned Chrome processes and temporary-profile growth; a missing teardown can eventually exhaust the host.
Rank #4
Local sessions versus remote WebDriver
With a local session, the browser and driver consume resources on the Ubuntu server where your code runs. This is straightforward for one host and keeps browser dependencies in one place. A remote session sends WebDriver commands to another machine or Grid, where that remote node owns the browser installation and its dependencies.
| Deployment | Best fit | Operational concern |
|---|---|---|
| Local headless Chrome | Small jobs, scheduled scripts, or a single test worker. | CPU, memory, browser updates, and concurrency limits are your host’s responsibility. |
| Remote WebDriver/Grid | Multiple workers, separate browser images, or centralized test infrastructure. | Maintain the remote nodes and network path; install and validate browser dependencies there, not only on the client. |
Troubleshooting ChromeDriver on Ubuntu Server
“Unable to obtain driver” or a driver download fails
- Cause: the binding cannot use Selenium Manager, outbound access is blocked, or the browser version cannot be resolved.
- Fix: upgrade to a current Selenium binding supported by your project, allow the required setup network access, or provision a deliberately pinned compatible driver and browser pair. Preserve the manager cache between runs when your deployment permits it.
“SessionNotCreatedException” or version-mismatch errors
- Cause: Chrome updated while the driver stayed old, or the driver targets a different browser channel.
- Fix: print both versions from the failing host, then resolve them as a pair using current Chrome for Testing metadata. Do not assume a driver that worked last month still matches an auto-updated browser.
Chrome starts and immediately exits
- Cause: missing Ubuntu libraries, an unwritable profile or temporary directory, insufficient shared memory, or a policy blocking the browser sandbox.
- Fix: run the minimal test as the service account, inspect the browser’s stderr and system logs, verify the browser installation documentation for your exact Ubuntu release, and correct permissions or resource limits. Avoid copying a random “fix” flag without understanding its security impact.
The page is blank, incomplete, or times out
- Cause: the application is JavaScript-heavy, a selector is not yet present, DNS/proxy access differs on the server, or the site blocks the host.
- Fix: add an explicit wait for a meaningful element, confirm DNS and proxy configuration from the server, capture browser logs where supported, and test the URL manually from the same network. A headless browser still needs the same outbound access as a normal browser.
The script works interactively but not as a service
- Cause: different environment variables, working directory, user permissions, or home/cache location.
- Fix: log the executable paths and versions, set a known working directory, grant access to the profile and temporary directories, and run the smoke test under the service manager’s exact account.
Or skip the browser setup
If your goal is a reliable website image rather than browser-test assertions, ScreenshotNeo provides a single HTTP request that returns PNG, JPEG, WebP, or PDF. It accepts consent banners before capture 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; each response identifies the page verdict and billing status in headers.
See the complete parameter reference in the ScreenshotNeo documentation. cURL:
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchcurl -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 also exposes an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Every feature is included on every plan; 1,000 screenshots per month are free with no card, and paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
Best Value
Frequently Asked Questions
Can Selenium run without an X server or desktop environment?
Yes. Chrome’s --headless=new mode runs without a visible browser window or desktop session.
Does Selenium Manager install Chrome itself?
Its documented role is resolving and downloading a compatible driver and caching it. You must still install and validate the browser and its Ubuntu dependencies.
Should I use close() or quit() after a test?
Use quit() for normal teardown because it ends the WebDriver session; close() only closes the current window.
Where does a remote WebDriver browser run?
On the remote WebDriver or Grid node. That machine, rather than the client process, needs the browser, driver, and operating-system dependencies.
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.

