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

In Selenium Java, run Chrome without a visible browser window by creating a ChromeOptions object, adding --headless=new, and passing those options to ChromeDriver. Selenium 4 uses this options-based API; the older setHeadless(true) convenience method is no longer available.

ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new");
WebDriver driver = new ChromeDriver(options);

What Chrome headless mode does

Headless Chrome runs without a visible user interface, so a Java program can navigate, inspect, test, print, or capture pages on a desktop, server, container, or CI worker without opening a window. It is still Chrome, not a simulated HTTP client: the browser loads pages, executes JavaScript, applies responsive layout rules, and exposes the resulting document through WebDriver.

Chrome’s current unified headless implementation follows the normal browser code path. Since Chrome 112, Chrome can create platform windows for headless operation without displaying them. From Chrome 132.0.6793.0 onward, the older implementation is distributed separately as the chrome-headless-shell binary. For ordinary Selenium Java automation, use the Chrome browser with a supported headless argument rather than assuming that shell is installed.

Prerequisites and compatibility

  • Install a Chrome or Chromium browser on the machine that will run the test.
  • Use Selenium 4 and its Java options classes, including ChromeOptions.
  • Keep the Chrome and ChromeDriver major versions aligned. A mismatch is a common reason for session-start failures.
  • Have a Java project that includes Selenium’s selenium-java library. Selenium Manager can obtain a driver automatically when a suitable driver is not already available in the environment.

Selenium’s Chrome integration is compatible with Chrome 75 and later. For a remote Selenium session, construct ChromeOptions in the same way and send it through the remote driver; the options object carries Chrome-specific arguments and capabilities.

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

Minimal Selenium Java example

This complete class starts current Chrome in the newer headless mode, sets a deterministic viewport, reads a page title, and always releases the browser process.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class HeadlessExample {
  public static void main(String[] args) {
    ChromeOptions options = new ChromeOptions();
    options.addArguments("--headless=new");
    options.addArguments("--window-size=1920,1080");

    WebDriver driver = new ChromeDriver(options);
    try {
      driver.get("https://example.com");
      System.out.println(driver.getTitle());
    } finally {
      driver.quit();
    }
  }
}

The --window-size value is a project choice, not a requirement for headless mode. Setting it explicitly makes responsive breakpoints and screenshots reproducible across developer machines and CI workers.

Choosing --headless=new or --headless

Argument When to use it Important qualification
--headless=new Preferred for current Chromium-based Chrome when you want the newer unified implementation. Verify that the Chrome version and CI image support it.
--headless Use when the environment or an existing compatibility policy specifically requires Chrome’s general headless flag. Its behavior depends on the Chrome version in the runtime; do not assume it selects the same implementation everywhere.

Selenium’s 2023 headless API guidance explains why the old convenience method was removed: developers should choose the desired mode explicitly through browser arguments. There is no universal performance guarantee that one mode is faster; measure your own page and workload if runtime matters.

Useful ChromeOptions settings

Set a predictable viewport

Use options.addArguments("--window-size=1440,900") (or another agreed dimension) when assertions depend on responsive CSS, when you compare screenshots, or when a page otherwise renders differently between machines.

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.

Use a separate profile for parallel jobs

Add --user-data-dir=/absolute/path/to/job-profile when a job needs persistent cookies or when parallel sessions must not share browser state. Give every concurrent job a different directory; sharing one profile can cause locks and cross-test contamination.

Use --no-sandbox only for a confirmed runtime need

Some container or CI configurations require --no-sandbox, but it is not a universal Selenium requirement. Investigate the container’s user, sandbox permissions, and security policy first, and apply the flag only when that environment specifically demands it.

Pass other Chrome arguments deliberately

Arguments affect security, rendering, networking, and profile state. Keep the smallest set that your test needs, document each one, and avoid copying a generic CI command line without understanding its effect.

Waiting for JavaScript applications

Headless mode does not make asynchronous pages instantly ready. driver.get() waits according to the page-load strategy, but a single-page application may continue rendering afterward. Prefer an explicit wait for the condition your test needs instead of a fixed sleep.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
WebElement result = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.cssSelector("main .result")));
System.out.println(result.getText());

Choose a selector that represents usable content, such as a results container or a logged-in navigation element. A wait for an arbitrary time can pass on a fast run and fail on a busy CI worker.

Capturing a screenshot from headless Chrome

For a Selenium screenshot, cast the driver to TakesScreenshot and save the returned bytes. The viewport is controlled by your window-size argument; a full-page image may require additional scrolling or browser-specific tooling.

import java.nio.file.Files;
import java.nio.file.Path;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;

byte[] png = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
Files.write(Path.of("page.png"), png);

Take the screenshot after the same explicit wait used by your assertion. Otherwise you can capture a loading skeleton even though the test later finds the finished element.

Or skip the browser setup

If your goal is a clean website image or PDF rather than interactive Selenium control, ScreenshotNeo provides a single HTTP request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

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

The API supports PNG, JPEG, WebP, and PDF output. Its 63 options include full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets and custom viewports, retina scale, PDF paper and margin controls, custom CSS and JavaScript, pre-capture clicks, selector or network-idle waits, request and resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous signed webhooks, 100-URL bulk calls, a usage API, and an OpenAPI specification. Common parameter names used by other screenshot APIs are accepted to ease migration.

Use the ScreenshotNeo documentation for the full parameter list. The following calls use https://stripe.com as the target.

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 an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Current listed plans are:

Plan Allowance Price
Free 1,000 shots/month $0
Starter 3,000 shots $5
Growth 15,000 shots $15
Pro 60,000 shots $39
Scale 250,000 shots $99
Business 1,000,000 shots $249

Every feature is included on every plan, and yearly billing gives two months free. Start with 1,000 free screenshots a month—no card required.

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

Troubleshooting ChromeDriver and headless runs

“This version of ChromeDriver only supports Chrome version …”

The browser and driver major versions do not match. Check both installed versions, update or pin them as one compatible pair, and let Selenium Manager resolve the driver when it is not deliberately managed by your build image.

setHeadless(true) does not compile

The convenience headless API was deprecated in Selenium 4.8.0 and removed in Selenium 4.10.0. Replace it with a ChromeOptions argument such as --headless=new, then pass the options to ChromeDriver.

The session cannot start in CI

  • Confirm Chrome is installed at the path used by the worker and that the process user can execute it.
  • Check the Chrome/ChromeDriver major-version pair.
  • Inspect container sandbox permissions and shared-memory limits before adding environment-specific flags.
  • Try the same options in a local container that matches CI, rather than debugging against a different desktop installation.

Pages look different from headful Chrome

Set an explicit window size, make device and timezone assumptions deliberate, and wait for the actual application-ready element. Responsive breakpoints, fonts, animation timing, and missing system resources can all change the rendered result. Temporarily remove nonessential arguments and run headful Chrome locally to isolate whether the difference comes from headless mode, the viewport, or the environment.

The test hangs or leaves Chrome processes behind

Keep browser creation inside a controlled lifecycle and call driver.quit() in a finally block. Add bounded explicit waits, capture diagnostic logs on timeout, and make sure each parallel worker owns its driver and profile directory.

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.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Headless-mode checklist

  1. Install Selenium 4, Chrome, and a compatible driver strategy.
  2. Create ChromeOptions.
  3. Add --headless=new unless your target environment requires the general --headless flag.
  4. Set --window-size when layout or screenshots must be repeatable.
  5. Use explicit waits for dynamic content.
  6. Use isolated profiles for parallel jobs that need browser state.
  7. Investigate sandbox and shared-memory constraints specifically in containers.
  8. Always call quit().

FAQ

Can the same ChromeOptions object be used with a remote WebDriver?

Yes. ChromeOptions is the Chrome-specific capabilities object Selenium uses for local and remote sessions; supply it when constructing the remote driver and let the Grid provide the browser process.

Does headless mode remove the need for waits?

No. Headless changes visibility, not application timing. JavaScript, network requests, and animations still determine when a page is ready for an assertion.

Is ScreenshotNeo a replacement for interactive Selenium tests?

No. ScreenshotNeo is aimed at rendered screenshots, page information, and PDFs through an API or MCP tools. Use Selenium when your test must click through a workflow, inspect browser state, or verify interactive behavior.

Frequently Asked Questions

Can the same ChromeOptions object be used with a remote WebDriver?

Yes. ChromeOptions is the Chrome-specific capabilities object Selenium uses for local and remote sessions; supply it when constructing the remote driver and let the Grid provide the browser process.

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

Does headless mode remove the need for waits?

No. Headless changes visibility, not application timing. JavaScript, network requests, and animations still determine when a page is ready for an assertion.

Is ScreenshotNeo a replacement for interactive Selenium tests?

No. ScreenshotNeo is aimed at rendered screenshots, page information, and PDFs through an API or MCP tools. Use Selenium when your test must click through a workflow, inspect browser state, or verify interactive behavior.

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.