QA How-To
How to Use Selenium DevTools in Selenium 4 in Java (2026)
Use selenium DevTools in Selenium 4 java to inspect network traffic, capture response bodies, block requests, add headers, and build reliable UI tests.
24 min read | 2,671 words
TL;DR
Cast a Chromium driver to HasDevTools, call getDevTools(), create a session, enable the required domain, and register listeners before loading the application. Match the versioned DevTools artifact to the browser protocol supported by your Selenium release, and isolate CDP code behind small helpers because it is Chromium-specific.
Key Takeaways
- Create one DevTools session per browser session and enable each CDP domain before using its commands or events.
- Keep selenium-java and the selenium-devtools-vNNN artifact on the same Selenium release.
- Register network listeners before navigation so the test does not miss early document and API requests.
- Filter captured traffic by URL and resource type instead of storing every browser event.
- Treat CDP as Chromium-specific and keep business assertions in portable WebDriver code when possible.
- Prefer WebDriver BiDi for new cross-browser capabilities that Selenium exposes there, while retaining CDP for Chromium gaps.
selenium DevTools in Selenium 4 java gives a test direct access to supported Chrome DevTools Protocol (CDP) commands and events. The practical sequence is simple: obtain DevTools from a Chromium-based driver, create a session, enable a domain such as Network, add listeners, and only then navigate or perform the action under test.
This extra channel is useful when normal WebDriver commands cannot expose enough browser detail. It can observe requests, inspect response metadata, retrieve selected response bodies, block resources, add request headers, read performance metrics, and collect evidence for frontend failures. It should complement user-visible assertions, not replace them.
This guide uses Selenium 4.45.0 and the versioned v145 DevTools bindings as a concrete 2026 example. CDP versions follow Chromium, so check the supported artifacts in your selected Selenium release when your browser moves. The design patterns remain the same even when the v145 package becomes v146 or later.
TL;DR
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
devTools.send(Network.enable(
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty()));
devTools.addListener(Network.responseReceived(), event ->
System.out.printf("%d %s%n",
event.getResponse().getStatus(),
event.getResponse().getUrl()));
driver.get("https://www.selenium.dev/");
| Need | Best Selenium interface | Portability |
|---|---|---|
| Click, type, locate, and assert UI state | WebDriver | Cross-browser |
| Chromium network events or CDP-only controls | DevTools/CDP | Chromium-based browsers |
| Standardized bidirectional events supported by Selenium | WebDriver BiDi | Growing cross-browser support |
| Browser console through standard logging | WebDriver logs when supported | Driver-dependent |
1. What selenium DevTools in Selenium 4 java Actually Provides
WebDriver and DevTools solve different testing problems. WebDriver models user-oriented browser automation through standardized commands. CDP is a browser instrumentation protocol exposed by Chromium. Selenium 4 supplies typed Java bindings for a supported set of CDP versions and a DevTools object that sends commands and receives events over a separate connection.
A command asks the browser to do something or return data. Network.enable() starts network tracking, Network.getResponseBody() requests a stored response body, and Network.setBlockedURLs() changes how matching requests are handled. An event is pushed by the browser. Network.requestWillBeSent(), Network.responseReceived(), and Network.loadingFailed() are common examples. This command-event distinction matters because a listener registered after navigation cannot recover events that have already happened.
CDP is appropriate when the test question concerns browser internals: Did the page call the correct endpoint? Which status code arrived? Was a resource blocked? Did the browser send a required header? It is usually the wrong layer for core behavior such as whether the customer can complete checkout. Keep those assertions in WebDriver so the suite remains readable and portable. For a broader tool decision, see Selenium vs Cypress for test automation.
2. Set Up Maven and Match the CDP Version
Use the same Selenium release for selenium-java and the versioned DevTools artifact. The artifact suffix is the CDP major version, not the Selenium version. This example targets the 2026 stable Selenium 4.45.0 line and CDP v145. If your build reports that no matching CDP implementation was found, inspect the Chromium major version and the DevTools artifacts shipped with your Selenium release. Upgrade Selenium as a unit instead of mixing jars.
<properties>
<maven.compiler.release>17</maven.compiler.release>
<selenium.version>4.45.0</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-devtools-v145</artifactId>
<version>${selenium.version}</version>
</dependency>
</dependencies>
Selenium Manager can resolve a compatible local driver when new ChromeDriver() starts, so most projects do not need to download a driver executable manually. That convenience does not solve a CDP binding mismatch. Selenium Manager manages browser-driver compatibility, while the versioned Java artifact supplies compile-time protocol classes.
Do not declare several DevTools versions hoping Selenium will choose one. That enlarges the dependency graph and makes imports ambiguous. Choose the artifact supported by the browser image used in CI, pin the image when stability matters, and schedule dependency upgrades deliberately.
3. Start a selenium DevTools in Selenium 4 java Session Correctly
ChromeDriver and EdgeDriver implement HasDevTools. You can call driver.getDevTools() directly on a ChromeDriver, or cast a more general WebDriver reference after verifying the capability. Create the CDP session once after the WebDriver session starts. When a test opens several tabs, create or reconnect the DevTools session with the intended window handle if the instrumentation must target a particular tab.
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
public final class DevToolsSessionExample {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
try {
if (!(driver instanceof HasDevTools hasDevTools)) {
throw new IllegalStateException("This driver does not expose DevTools");
}
DevTools devTools = hasDevTools.getDevTools();
devTools.createSession(driver.getWindowHandle());
driver.get("https://www.selenium.dev/");
} finally {
driver.quit();
}
}
}
A DevTools session is attached to the active browser session. Do not put one static DevTools instance behind all parallel tests. Each WebDriver instance needs its own object, listeners, and lifecycle. Close or quit the WebDriver in finally or test teardown even after an assertion fails. If the framework reuses drivers, call clearListeners() between tests or create narrowly scoped listeners so one test does not consume another test's traffic.
4. Capture Requests, Responses, and Failed Loads
Network observation is the most common Selenium 4 DevTools Java use case. Enable the Network domain and register listeners before navigation. Store only the fields required by the assertion. Copying every header and body into a global list wastes memory and can leak credentials into logs.
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v145.network.Network;
public final class NetworkAudit {
public static void main(String[] args) {
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
List<String> apiResponses = new CopyOnWriteArrayList<>();
try {
devTools.createSession();
devTools.send(Network.enable(
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty()));
devTools.addListener(Network.requestWillBeSent(), event -> {
String url = event.getRequest().getUrl();
if (url.contains("/api/")) {
System.out.println("REQUEST " + event.getRequest().getMethod() + " " + url);
}
});
devTools.addListener(Network.responseReceived(), event -> {
String url = event.getResponse().getUrl();
if (url.contains("/api/")) {
apiResponses.add(event.getResponse().getStatus() + " " + url);
}
});
devTools.addListener(Network.loadingFailed(), event ->
System.err.println("FAILED " + event.getErrorText()));
driver.get("https://www.selenium.dev/");
apiResponses.forEach(System.out::println);
} finally {
driver.quit();
}
}
}
CopyOnWriteArrayList avoids unsafe mutation when event callbacks and the test thread overlap. For a high-volume capture, a concurrent queue is usually cheaper. The test should wait for a specific application outcome or a matched event, not sleep for an arbitrary period. Network evidence becomes especially useful alongside structured API error handling and negative testing.
5. Retrieve a Selected Response Body
A responseReceived event includes a request ID. Pass that ID to Network.getResponseBody() while the browser still retains the resource. Do this only for the endpoint under test. Binary data may be Base64 encoded, large bodies increase memory use, and some cached or redirected responses may no longer have a retrievable body.
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v145.network.Network;
public final class ResponseBodyExample {
public static void main(String[] args) throws Exception {
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
CompletableFuture<String> bodyFuture = new CompletableFuture<>();
try {
devTools.createSession();
devTools.send(Network.enable(
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty()));
devTools.addListener(Network.responseReceived(), event -> {
String url = event.getResponse().getUrl();
if (url.endsWith("/api/profile") && !bodyFuture.isDone()) {
try {
var result = devTools.send(Network.getResponseBody(event.getRequestId()));
bodyFuture.complete(result.getBody());
} catch (RuntimeException error) {
bodyFuture.completeExceptionally(error);
}
}
});
driver.get("https://app.example.test/account");
String body = bodyFuture.get(10, TimeUnit.SECONDS);
if (!body.contains("email")) {
throw new AssertionError("Profile response did not contain email");
}
} finally {
driver.quit();
}
}
}
Replace the illustrative URL with a controlled test environment. In production-grade code, deserialize JSON with Jackson and assert a schema or selected fields rather than searching a raw string. Never print access tokens, cookies, personal data, or complete response bodies to shared CI logs.
6. Add Headers and Block Unwanted Resources
CDP can modify Chromium network behavior before the page loads. Network.setExtraHTTPHeaders() adds headers to subsequent requests in that DevTools session. Network.setBlockedURLs() rejects matching URLs, which is useful for verifying fallback behavior when analytics, images, or a known dependency is unavailable. These are browser-level controls, so make the modified condition obvious in the test name.
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v145.network.Network;
import org.openqa.selenium.devtools.v145.network.model.Headers;
public final class NetworkControlExample {
public static void main(String[] args) {
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
try {
devTools.createSession();
devTools.send(Network.enable(
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty()));
devTools.send(Network.setExtraHTTPHeaders(
new Headers(Map.of("X-Test-Run", "checkout-fallback"))));
devTools.send(Network.setBlockedURLs(
List.of("*://cdn.example.test/promotions/*")));
driver.get("https://shop.example.test/cart");
String text = driver.findElement(
org.openqa.selenium.By.id("promotion-status")).getText();
if (!text.equals("Promotions unavailable")) {
throw new AssertionError("Fallback message was not shown");
}
} finally {
driver.quit();
}
}
}
Extra headers apply broadly, not only to one API call. Avoid overriding security-sensitive headers unless that condition is the explicit subject of the test. Clear test data through a fresh browser session rather than depending on an undocumented inverse command. For deeper contract validation, use a dedicated API client and an OpenAPI schema testing strategy.
7. Synchronize Event-Driven Assertions Without Sleeps
DevTools events arrive asynchronously. A WebDriver element becoming visible does not guarantee that an unrelated analytics request has finished, and navigation completion does not guarantee that a single-page application has made its later API calls. Model the exact event the test needs with a CompletableFuture, CountDownLatch, or thread-safe queue. Apply a bounded timeout so failure is diagnostic rather than endless.
CompletableFuture<Integer> orderStatus = new CompletableFuture<>();
devTools.addListener(Network.responseReceived(), event -> {
if (event.getResponse().getUrl().contains("/api/orders/")) {
orderStatus.complete(event.getResponse().getStatus());
}
});
driver.findElement(By.id("place-order")).click();
int status = orderStatus.get(10, TimeUnit.SECONDS);
if (status != 201) {
throw new AssertionError("Expected order status 201 but was " + status);
}
Register the listener before the click. Complete the future only once and filter narrowly enough that a background polling request cannot satisfy the assertion. Keep the UI assertion too, because a 201 response does not prove that the application rendered the confirmation correctly. This two-layer pattern provides fast diagnosis: the API event identifies transport behavior, and WebDriver verifies customer-visible behavior.
Avoid Thread.sleep() as a synchronization mechanism. It can still miss a slow event and always penalizes a fast run. A future with a timeout ends as soon as the expected event arrives and names the missing condition when it does not.
8. Design a Maintainable DevTools Test Layer
CDP types change more often than ordinary WebDriver APIs because they track Chromium. Contain versioned imports in a small adapter such as ChromiumNetworkProbe. Let tests ask domain questions like waitForStatus(urlPredicate) instead of importing org.openqa.selenium.devtools.v145 throughout page objects. When the CDP version changes, the adapter becomes the main compilation boundary.
Do not mix DevTools listeners into page objects that represent screens. Page objects should describe user interactions and visible state. A separate probe or fixture should own protocol setup, captured events, redaction, and teardown. This separation also makes it possible to skip or replace the probe on Firefox and Safari runs.
A useful test pyramid for browser instrumentation has three layers:
- Portable WebDriver scenarios for critical customer journeys.
- A smaller Chromium suite with CDP assertions for network, performance, or failure-mode risks.
- Direct API tests for broad payload, schema, and negative coverage.
Tag CDP-dependent tests and select a compatible CI browser image. If parallel tests share a proxy, account, or backend state, CDP isolation does not protect those external resources. Maintain ordinary test-data isolation as well.
9. Understand CDP, WebDriver BiDi, and Proxy Tradeoffs
Selenium documentation treats CDP support as transitional because CDP is Chromium-specific and versioned. WebDriver BiDi is the standards-based bidirectional direction. In 2026, the correct choice is capability by capability, not a blanket rewrite. If Selenium exposes the required feature through BiDi across your target browsers, prefer it for new cross-browser infrastructure. If a necessary Chromium feature exists only through the typed DevTools bindings, CDP remains practical.
| Approach | Strength | Limitation | Best use |
|---|---|---|---|
| Selenium DevTools/CDP | Deep Chromium access with typed Java commands | CDP version coupling and limited portability | Chromium network and browser instrumentation |
| WebDriver BiDi | Standards-oriented event channel | Coverage still varies by binding, browser, and feature | New portable logging and network workflows |
| HTTP proxy | Browser-independent traffic capture | TLS setup, environment complexity, and incomplete browser context | Organization-wide capture or mutation |
| Direct API client | Fast, precise payload assertions | Does not exercise browser integration | Contract and negative API testing |
Choose the least specialized layer that answers the test question. A direct API test is better than launching a browser solely to validate fifty response fields. CDP is better when the question is whether the actual browser page sent a header or handled a blocked resource. WebDriver remains best for user-observable outcomes.
10. Diagnose Version and Runtime Failures
The most recognizable setup problem is a warning that Selenium cannot find a matching CDP implementation. It usually means the Chromium major version is newer than the DevTools modules known to the selected Selenium release. Upgrade Selenium and the versioned artifact together, or use a compatible pinned browser image. Do not suppress the warning and assume typed commands are safe.
Compilation errors after changing v145 to another package can reflect real protocol signature changes. Read the generated API for that version and update the adapter. Do not guess additional Optional.empty() arguments. A runtime DevToolsException can also mean that the target closed, the response body was evicted, or a command is unsupported in the current context. Capture the browser version, Selenium version, command name, target URL pattern, and sanitized error text.
When events seem absent, verify this order: create session, enable domain, add listener, trigger action, wait for the precise event. Also confirm that a service worker or browser cache did not satisfy the resource differently. Reproduce once with cache disabled only if cache behavior is not part of the scenario. If the same workflow fails in portable WebDriver code, troubleshoot that layer before blaming CDP.
11. Test Caching, Service Workers, and Redirects Intentionally
Network events are not always a one-request, one-response story. A redirect creates related request activity, a service worker may fulfill traffic without the path you expected, and a memory or disk cache can change event fields and timing. Do not disable these browser behaviors globally just to simplify assertions. Decide whether cache, redirect, or service-worker behavior belongs to the requirement, then capture the fields that distinguish the paths.
For a cold-load scenario, start with a fresh browser profile and enable Network before navigation. For a warm-load scenario, navigate once to populate browser state, drain or clear your test-side event collection, then perform the measured action. Keep the same browser session only when retained cache is intentional. A new WebDriver session is the clearest reset for unrelated tests.
When testing redirects, correlate events by request ID and assert the final URL and status appropriate to the application. Do not count raw responseReceived events and assume one count equals one logical API operation. When a service worker is in scope, record fromServiceWorker or related response metadata exposed by the selected CDP version. If the application should bypass service workers in a particular test environment, configure that environment explicitly rather than silently changing the browser in a generic fixture.
Cache-control validation often belongs in direct HTTP tests, while DevTools can confirm what the real page observed. Combine the layers: verify header contracts cheaply through an API client, then keep one browser scenario for the customer-visible consequence, such as offline recovery or an updated asset after deployment.
Interview Questions and Answers
Q: What is the purpose of DevTools support in Selenium 4 Java?
It exposes selected Chrome DevTools Protocol commands and events through typed Java bindings. Teams use it for browser details that standard WebDriver does not provide, such as Chromium network events, response bodies, blocked URLs, and performance metrics. It complements rather than replaces WebDriver.
Q: Why must Network.enable() run before listeners are useful?
CDP domains generally need to be enabled before they emit the relevant events. The listener must also be registered before the action that creates the request. Otherwise, early document or API events can be missed.
Q: What causes a CDP version mismatch?
The Chromium major version and the versioned DevTools module supported by Selenium are out of alignment. The fix is to upgrade Selenium and its DevTools artifact together or run a compatible browser version. Driver resolution alone does not add missing Java protocol classes.
Q: How would you make an asynchronous network assertion reliable?
I would register a narrowly filtered listener before the UI action, complete a CompletableFuture when the matching event arrives, and wait with a short explicit timeout. I would use a thread-safe collection if multiple events matter and keep a separate UI assertion.
Q: When would you avoid Selenium DevTools?
I would avoid it for ordinary clicks, text assertions, and broad API contract testing. WebDriver is more portable for user behavior, while a direct HTTP client is faster and clearer for payload validation. CDP is justified when browser integration itself is under test.
Q: How do you prevent sensitive data from leaking through network logs?
Filter by endpoint and capture only necessary fields. Redact authorization, cookie, and personal-data headers before storage, and do not log full bodies by default. Apply normal CI artifact retention and access controls to any diagnostic capture.
Q: What is the relationship between CDP and WebDriver BiDi?
CDP is Chromium's browser-specific protocol, while WebDriver BiDi is a standards-oriented bidirectional protocol. Selenium is expanding BiDi support, so I prefer BiDi where the required feature is mature across target browsers. I keep CDP behind an adapter for Chromium-only gaps.
Common Mistakes
- Registering listeners after
driver.get()or after the click that sends the request. Early events are already gone. - Adding
selenium-devtools-v145at a different Selenium version fromselenium-java. This can create binary incompatibility. - Sharing a static
DevToolsobject across parallel drivers. Sessions and listeners then cross test boundaries. - Capturing every response body. This slows tests, consumes memory, and risks exposing secrets.
- Using network status as the only assertion. A successful response does not prove correct rendering or usable behavior.
- Hiding arbitrary sleeps inside a helper. Wait for a named event with a bounded timeout instead.
- Spreading versioned CDP imports across page objects. Keep them in a protocol adapter.
- Assuming CDP tests are cross-browser because they use Selenium. The DevTools implementation described here targets Chromium-based drivers.
Conclusion
The reliable pattern for selenium DevTools in Selenium 4 java is to match dependencies, create a session, enable the required domain, register focused listeners before the trigger, and synchronize on the specific event. Use the resulting evidence to explain browser behavior, while keeping customer-visible assertions in ordinary WebDriver code.
Start with one valuable scenario, such as verifying the status and UI outcome of a checkout request. Wrap the versioned CDP code in a small adapter, redact captured data, and add more instrumentation only when it answers a concrete product risk.
Interview Questions and Answers
How do you initialize a DevTools session in Selenium 4 Java?
I obtain DevTools from a Chromium driver through HasDevTools, call createSession(), enable the domain I need, and register listeners before the action. I bind the object to the same lifecycle as its WebDriver session.
What is the difference between a CDP command and a CDP event?
A command is sent by the test to request an action or result, such as Network.getResponseBody. An event is pushed by the browser, such as Network.responseReceived. Event listeners must be active before the triggering browser activity.
How do you assert a network call without Thread.sleep?
I register a filtered listener and complete a CompletableFuture or CountDownLatch when the matching event arrives. The test waits with a bounded timeout and reports the endpoint it expected. I also retain a UI assertion for the customer-visible result.
Why is the selenium-devtools artifact versioned by Chromium?
CDP schemas evolve with Chromium, and Selenium generates typed bindings for selected protocol versions. The vNNN artifact identifies that protocol major. It should use the same Selenium library release as selenium-java.
How would you structure DevTools code in a large framework?
I would place version-specific imports in a small adapter or test fixture, separate from page objects. Tests would call domain methods such as waitForResponseStatus. This keeps protocol upgrades and Chromium-only skips localized.
What are the main risks of capturing response bodies in UI tests?
Bodies can be large, unavailable after eviction, binary or Base64 encoded, and full of secrets or personal data. I capture only selected endpoints, parse only necessary fields, redact diagnostics, and use direct API tests for broad contract coverage.
When is WebDriver BiDi preferable to CDP?
BiDi is preferable when the required feature is supported by Selenium and the target browsers because it follows a cross-browser standard. CDP remains useful for Chromium-specific depth. I choose per capability and keep either instrumentation layer outside business-facing page objects.
Frequently Asked Questions
How do I open DevTools in Selenium 4 Java?
Use a Chromium driver that implements HasDevTools, call getDevTools(), and then call createSession(). Enable the required domain and add listeners before navigating or triggering the action.
Which Maven dependency is needed for Selenium DevTools Java?
Add selenium-java and a supported versioned artifact such as selenium-devtools-v145 at the same Selenium release. The vNNN suffix must match a CDP version supported by that Selenium release and your Chromium environment.
Can Selenium DevTools capture API response bodies?
Yes. Listen for Network.responseReceived, select the intended request ID, and send Network.getResponseBody before the browser discards it. Limit capture to required endpoints and redact sensitive content.
Does Selenium DevTools work with Firefox?
The typed CDP workflow in this guide is for Chromium-based drivers. Use portable WebDriver commands or supported WebDriver BiDi features when Firefox and broader cross-browser behavior are required.
Why does Selenium say it cannot find a matching CDP implementation?
The browser's CDP major version is not represented by the DevTools modules in your Selenium installation. Upgrade Selenium and its versioned DevTools artifact together, or use a compatible pinned Chromium image.
Should I use CDP or WebDriver BiDi in 2026?
Prefer WebDriver BiDi when Selenium exposes the needed capability reliably across your target browsers. Keep CDP for Chromium-specific features or gaps, and isolate it so future migration is contained.
Can I use Selenium DevTools tests in parallel?
Yes, if every test owns its WebDriver and DevTools session and uses thread-safe event storage. Do not share listeners or a static DevTools object across sessions, and preserve normal test-data isolation.
Related Guides
- How to Use Selenium Actions clickAndHold in Java (2026)
- How to Use Selenium Actions moveToElement in Java (2026)
- How to Use Selenium BiDi network in Java (2026)
- How to Use Selenium browser console logs in Java (2026)
- How to Use Selenium By cssSelector in Java (2026)
- How to Use Selenium By xpath dynamic in Java (2026)