How to Use Java 11 HttpClient with Selenium
Configure Selenium to use Java 11’s built-in HTTP client, with version guidance, runnable setup, Grid instructions, troubleshooting, and practical limits.
Selenium uses an HTTP and WebSocket transport to communicate with browser drivers, Selenium Grid, and DevTools or BiDi sessions. Java 11’s built-in HTTP client is one transport option; it does not replace the WebDriver API you use to control the browser.
Selenium introduced support for the JDK client in 4.5.0 as an optional component. Selenium’s published guidance says it is the default from 4.14 onward. For releases where you need to select it explicitly, use matching Selenium artifact versions and set webdriver.http.factory=jdk-http-client before Selenium creates the relevant client. See Selenium’s Java 11 HTTP client guidance.
1. Check your Selenium and Java versions
First check the version used by your project and the Java runtime used to launch it. Java’s java.net.http module is part of Java 11 and later. The Selenium setup depends on the Selenium release:
| Selenium version | What to do |
|---|---|
| Before 4.5.0 | The cited Selenium guidance does not describe support for this JDK client. Upgrade to a supported Selenium release if you need this transport. |
| 4.5.0 through 4.13.x | Add the matching selenium-http-jdk-client artifact and select it with the system property. |
| 4.14 or later | Selenium’s published guidance says the JDK client is used by default. You generally do not need to add the optional artifact just to select the default, but follow the documentation for your exact release if you need explicit behavior. |
These are release-specific statements from Selenium’s guidance, not a substitute for checking the release notes and documentation for the version you actually deploy.
2. Configure a Java project
For explicit configuration on a release that requires the optional module, keep selenium-java and selenium-http-jdk-client at the same version. The following Maven dependencies show the pattern. Replace ${selenium.version} with the same supported Selenium version for both artifacts.
<properties>
<maven.compiler.release>11</maven.compiler.release>
<selenium.version>YOUR_SELENIUM_VERSION</selenium.version>
</properties>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-http-jdk-client</artifactId>
<version>${selenium.version}</version>
</dependency>
</dependencies>
Choose a real Selenium version available in your project’s repositories. Do not leave the placeholder as-is. For Selenium 4.14 or later, use the release’s guidance to decide whether the explicit artifact is needed in your setup.
Set the property before constructing the driver or otherwise triggering creation of Selenium’s HTTP client:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class SeleniumJdkHttpClient {
public static void main(String[] args) {
System.setProperty("webdriver.http.factory", "jdk-http-client");
WebDriver driver = new ChromeDriver();
try {
driver.get("https://example.com");
System.out.println(driver.getTitle());
} finally {
driver.quit();
}
}
}
This example uses Selenium’s normal WebDriver API. The property selects the transport used under that API; it does not make HttpClient a browser automation interface, and it does not mean you should replace driver.get with a raw HTTP request.
Set the property at JVM startup
You can set the same system property on the Java command line, which avoids setting it in application code:
java -Dwebdriver.http.factory=jdk-http-client -cp "..." SeleniumJdkHttpClient
With Maven Surefire, a JVM system property can also be supplied through the test configuration or command line. Ensure it reaches the forked test JVM, not only Maven’s own process. The exact configuration depends on your build plugin and project.
3. Configure Selenium Grid
For Grid, the JDK HTTP client extension must be available to the Selenium Server process. Selenium’s Grid getting-started guidance documents adding the matching artifact with --ext and setting the factory property. Use the same Selenium release for the extension as for the server.
java -Dwebdriver.http.factory=jdk-http-client \
-jar selenium-server-YOUR_SELENIUM_VERSION.jar standalone \
--ext selenium-http-jdk-client-YOUR_SELENIUM_VERSION.jar
Replace both placeholders with actual artifact filenames for the same release, and make sure the files are accessible from the directory where the command runs. Consult Selenium Grid’s getting-started guide for the command options supported by your version.
Hub, Node, and distributed deployments
In a distributed deployment, apply the extension and property to each relevant Selenium component as described by Selenium’s Grid guidance. Do not assume a setting on one process configures every other process. If you use a container or service manager, place the artifact on the server classpath and pass the JVM property to the process that needs to create the HTTP client.
4. What the JDK client changes
Java’s java.net.http module provides HTTP/1.1, HTTP/2, and WebSocket APIs, including HttpClient, HttpRequest, HttpResponse, and WebSocket. Selenium uses its transport for WebDriver commands, client-to-Grid commands, communication between Grid components, and DevTools or BiDi sessions. WebDriver remains the browser-control API, while BiDi provides a WebSocket-based way to receive browser events.
See the Java SE 11 java.net.http API documentation and Selenium’s WebDriver documentation for the respective API roles.
5. Troubleshooting
| Symptom | Likely cause | What to check |
|---|---|---|
| “Unable to create HttpClient factory” or a factory cannot be found | The JDK client extension is missing from the runtime classpath, or the artifact does not match the Selenium version. | Add selenium-http-jdk-client for the applicable release, align its version with the other Selenium artifacts, and confirm the dependency is present in the process that launches Selenium. |
| The property appears to have no effect | It was set after Selenium initialized the relevant client, misspelled, or set in a different JVM. | Use the exact key and value webdriver.http.factory=jdk-http-client. Set it at JVM startup or before creating the driver/client. For tests, verify the property reaches the test JVM. |
| Local runs work but Grid fails | The Grid server or another relevant component lacks the extension or property. | Check the server classpath and --ext argument. In distributed mode, apply the documented setup to each relevant component. |
| Dependency resolution fails | The version placeholder was not replaced, the artifact version is unavailable in the configured repository, or versions are inconsistent. | Use a published version appropriate for your project, keep Selenium artifacts aligned, and refresh the build’s dependency resolution. |
| Behavior changes after a Selenium upgrade | Default selection or configuration behavior can differ across releases. | Review the documentation and release notes for the exact Selenium version. The 4.14 default described in the 2022 article is version guidance, not a promise about every future configuration detail. |
Calling cancel() does not stop an in-flight request |
Java documents that cancellation of a returned CompletableFuture may not interrupt the underlying operation. |
Treat cancellation as completion of the future, not a guarantee that network work stopped. Design timeouts and cleanup around the APIs and Selenium version in use. |
6. Performance, reliability, and cost
The cited official sources do not provide a benchmark showing that the JDK client is faster than Selenium’s alternative transport in a particular workload. Choose based on release support, classpath and Grid deployment requirements, and observed compatibility in your own environment. Do not infer a speedup merely from using the JDK implementation.
For reliability, verify the transport setting in the same process that communicates with the driver or Grid, keep related Selenium artifacts on a consistent release, and test the topology you deploy. Java’s asynchronous API has a cancellation caveat: cancelling a CompletableFuture may not interrupt the underlying operation. No separate paid component is required by the setup described here; the documented pieces are Java and Selenium artifacts.
Or skip the browser setup
If your goal is a website screenshot rather than browser automation, ScreenshotNeo provides a screenshot API and MCP server. It is separate from Selenium and does not control a browser through WebDriver. One GET request returns an image or PDF; see the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
- Cookie banners are accepted and removed before capture, along with known consent platforms, newsletter popups, and chat widgets; each step can be turned off.
- Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Response headers report the page verdict and billing status.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdffor AI agents and MCP clients. - The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. All features are on every plan.
Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
FAQ
Does Java 11 HttpClient replace Selenium WebDriver?
No. It is a transport Selenium can use to communicate with browser drivers, Grid, and DevTools or BiDi sessions. WebDriver remains the browser automation API.
Do I need to configure the property on Selenium 4.14 and later?
Selenium’s published 2022 guidance says the JDK client is the default from 4.14. Check the documentation for your exact release before adding explicit configuration.
Can I use the JDK client with Selenium Grid?
Yes, following Selenium’s documented server setup: make the extension available with --ext, set the factory property, and apply the setup to each relevant component in distributed deployments.
Does this setting make my own Java HTTP requests use Selenium’s transport?
No. It selects Selenium’s internal transport. Your application’s own requests use the Java HTTP API only when your code creates and uses an HttpClient.


