Selenium DevTools for Advanced Chrome Automation

Selenium DevTools provides access to Chrome debugging capabilities through CDP. Explore commands for network, cookies, performance, and automation.

Written by Sujay Sawant Sujay Sawant
Reviewed by Ashwani Pathak Ashwani Pathak
Last updated: 7 August 2026 27 min read

Key Takeaways

  • Selenium DevTools adds browser-level visibility to WebDriver by exposing network traffic, console errors, performance metrics, and emulation controls beyond page-level checks.
  • Use CDP selectively for debugging, request inspection, mocking, and controlled environment simulation while keeping normal user interactions in Selenium WebDriver.
  • Isolate CDP helpers, clean up overrides, and record browser and protocol versions to reduce failures caused by event timing or Chrome updates.

When you test a modern web application in Chrome, a failed click or missing element may be only the visible symptom. The actual cause could be a blocked request, console error, slow resource, or incorrect browser event.

Selenium DevTools lets you look beyond the page by connecting Selenium with the Chrome DevTools Protocol (CDP). You can inspect network traffic, capture browser logs, emulate different conditions, and collect performance data during the same test.

Whether you are learning CDP or extending an existing framework, the following sections explain where these capabilities fit into practical Selenium testing.

What are Selenium Dev Tools?

Selenium DevTools is part of the Selenium framework and integrates with Chrome Debugging Protocol (CDP) to provide direct access to browser internals. Testers can perform tasks such as capturing console logs, throttling network conditions, and simulating device settings.

It is an important tool for enriching web automation and debugging beyond traditional Selenium functionalities.

What is Chrome Debugging Protocol (CDP)?

The Chrome Debugging Protocol (CDP) allows developers to communicate directly with the Chrome browser engine.

It supports advanced operations like log capture, network request monitoring, and changes in browser settings, which are integral for tasks requiring specific control over the behaviour of the browser.

CDP also supports some of the functionalities, namely network throttling and HTTP requests intercepting capabilities along with simulating the settings of various devices, with Selenium’s help through DevTools for interaction with CDP.

Differences Between Traditional Selenium Features and CDP Enhanced Automation

Traditional Selenium WebDriver controls the browser through standard commands such as opening pages, locating elements, clicking controls, and reading their state. It works well when your test needs to interact with the application as a user would.

CDP-enhanced automation serves a different purpose. It gives Selenium access to lower-level browser activity in Chrome and other Chromium-based browsers. This helps when you need to inspect requests, listen for browser events, capture detailed logs, or change conditions that WebDriver does not control directly.

AspectTraditional Selenium WebDriverCDP-Enhanced Automation
Primary purposeAutomates user actions and validates application behaviour through the browser interface.Observes and controls browser internals during test execution.
Browser communicationSends commands and receives a response for each action.Can listen for browser events such as requests, responses, and console messages as they occur.
Element interactionLocates and interacts with buttons, fields, links, frames, alerts, and other page elements.Does not replace WebDriver element commands. It adds browser-level information around those interactions.
Network inspectionStandard WebDriver does not provide complete access to request and response traffic.Can inspect network requests, response details, headers, failures, and loading events.
Request modificationOffers no standard command for changing an outgoing request or replacing a response.Can block requests, modify headers, provide mocked responses, or simulate failed services.
Browser logsMay expose selected browser logs depending on the driver and configuration.Can subscribe to detailed console and JavaScript events while the test is running.
Performance dataCan measure test timings but does not provide detailed browser performance metrics by default.Can collect browser metrics and inspect resource-loading activity for targeted performance analysis.
Device and environment emulationSupports window resizing and browser-specific mobile configuration.Can override device metrics, user agents, geolocation, timezone, and network conditions where the browser supports them.
Browser coverageWebDriver is designed for cross-browser automation across Chrome, Edge, Firefox, Safari, and other supported browsers.CDP support is tied mainly to Chrome and Chromium-based browsers.
Version stabilityUses the WebDriver standard, which provides a more stable cross-browser interface.CDP commands can change between browser versions. The browser and supported DevTools version must remain compatible.
Best suited forFunctional testing, regression testing, end-to-end workflows, and cross-browser validation.Network debugging, response mocking, console monitoring, browser emulation, and targeted performance checks.

You should not treat CDP as a replacement for normal Selenium commands. Keep WebDriver responsible for the main user journey. Add CDP only where the test needs information or control below the page level.

For example, WebDriver can submit a login form and verify that the account page appears. CDP can support the same test by checking whether the authentication request returned an error, whether a required script failed to load, or whether a console exception occurred during the redirect.

CDP is also browser-specific and its APIs are not guaranteed to remain stable. Selenium describes its CDP support as temporary while the standards-based WebDriver BiDi implementation continues to expand. Tests that depend heavily on CDP should therefore keep that logic separate from the main framework and account for browser-version changes.

Key Features of Selenium DevTools

Selenium DevTools expands traditional Selenium capabilities by offering advanced browser automation and debugging tools. Below are its key features:

  • Network Interception and Monitoring: Testers can intercept and monitor network requests and responses to analyze API calls, debug network issues, and enhance web performance.
  • Mocking Network Requests and Responses: The tool allows testers to mock specific network requests and customize responses, making it easier to test scenarios like server errors or delayed responses.
  • Performance Profiling: It provides detailed performance metrics such as page load times, CPU usage, and memory consumption. These insights help identify bottlenecks and optimize application performance.
  • Capturing Console Logs and Browser Events: Selenium DevTools captures browser console logs and critical events, such as JavaScript errors, to simplify debugging and troubleshooting.
  • Emulating Devices and Geolocation Settings: Testers can simulate mobile devices, screen resolutions, and geolocations, enabling efficient testing of responsive designs and location-specific features.

Setting Up Selenium Dev Tools

Selenium 4 provides direct access to Chrome DevTools Protocol commands, so you do not need a separate DevTools package for Python. You need a recent Selenium version, Chrome or another Chromium-based browser, and a working WebDriver session. CDP features depend on the browser version and may change between releases.

Prerequisites

Before starting, make sure your system has:

  • Python 3 installed
  • Google Chrome or another Chromium-based browser
  • Selenium 4
  • pip for installing Python packages
  • A code editor or Python IDE

Older Selenium setups often required you to download ChromeDriver and add it to the system path. Selenium Manager now handles driver discovery and downloads when you create a driver without providing its location. This support has been available since Selenium 4.6.

You may still need to manage the driver manually in restricted environments where automatic downloads are blocked.

Step-by-Step Setup Process to Set Up Selenium Dev Tools

Start by creating a project directory and an optional virtual environment. A virtual environment keeps the Selenium version and other dependencies separate from your system-level Python packages.

mkdir selenium-devtools-demo

cd selenium-devtools-demo

python -m venv venv

Activate the environment on Windows:

venv\Scripts\activate

On macOS or Linux:

source venv/bin/activate

Install Required Libraries

Install Selenium through pip:

pip install selenium

You can confirm the installed version with:

pip show selenium

The Selenium package includes the Python WebDriver bindings required to start Chrome and send CDP commands. Selenium’s official downloads page listed Selenium 4.46.0 as the stable Python release on July 11, 2026. You should still check your project requirements before upgrading an existing test suite.

Configuration Code for Enabling DevTools

The following example starts Chrome and sends a CDP command through execute_cdp_cmd():

from selenium import webdriver

from selenium.common.exceptions import WebDriverException




driver = None



try:

    driver = webdriver.Chrome()



    browser_details = driver.execute_cdp_cmd(

        "Browser.getVersion",

        {}

    )



    print("Browser:", browser_details["product"])

    print("Protocol version:", browser_details["protocolVersion"])



    driver.get("https://example.com")



except WebDriverException as error:

    print(f"Unable to start the browser or execute CDP: {error}")



finally:

    if driver:

        driver.quit()

webdriver.Chrome() creates the browser session. Selenium Manager finds a compatible driver when one has not been configured manually. The Browser.getVersion command then confirms that Selenium can communicate with the browser through CDP.

You do not need to create a separate DevTools session when using execute_cdp_cmd() in Python. The method accepts a CDP command name and a dictionary containing its parameters. It returns the browser response as a Python dictionary.

Once this setup works, you can enable specific CDP domains as required:

driver.execute_cdp_cmd("Network.enable", {})

driver.execute_cdp_cmd("Performance.enable", {})

Enabling a domain allows the browser to process related commands. For example, the Network domain supports operations involving requests and responses, while the Performance domain exposes browser performance metrics.

Keep CDP-specific code in a separate helper or service class when adding it to a larger framework. CDP does not provide a stable, cross-browser API, and Selenium plans to replace applicable CDP use cases with WebDriver BiDi as its support develops.

Code Examples for Using Selenium DevTools

Here are examples of how Selenium DevTools can be used for advanced automation and testing.

1. Intercepting Network Requests

Code to capture and log HTTP requests and responses is useful for monitoring API calls during tests

from selenium import webdriver  



# Set up ChromeDriver and DevTools  

driver = webdriver.Chrome()  

dev_tools = driver.devtools  

dev_tools.create_session()  



# Enable network monitoring  

dev_tools.send_command("Network.enable")  



# Capture HTTP requests and responses  

def capture_request(data):  

    print("Request:", data)  



def capture_response(data):  

    print("Response:", data)  



dev_tools.add_listener("Network.requestWillBeSent", capture_request)  

dev_tools.add_listener("Network.responseReceived", capture_response)  



driver.get("https://example.com")  

driver.quit()

2. Mocking Network Responses

Testing frontend behaviour with simulated data requires mocking or modifying server responses:

from selenium import webdriver  



# Set up ChromeDriver and DevTools  

driver = webdriver.Chrome()  

dev_tools = driver.devtools  

dev_tools.create_session()  



# Enable network monitoring  

dev_tools.send_command("Network.enable")  



# Mock response  

mock_response = {  

    "id": 1,  

    "result": {"response": "mocked data"}  

}  



dev_tools.send_command("Fetch.enable", {"patterns": [{"urlPattern": "*"}]})  



def modify_response(data):  

    dev_tools.send_command("Fetch.fulfillRequest", {  

        "requestId": data["requestId"],  

        "responseCode": 200,  

        "body": mock_response  

    })  



dev_tools.add_listener("Fetch.requestPaused", modify_response)  



driver.get("https://example.com")  

driver.quit()

3. Capturing Console Logs

Extracting browser console logs during test execution is needed for debugging JavaScript errors in the application.

from selenium import webdriver  



# Set up ChromeDriver and DevTools  

driver = webdriver.Chrome()  

dev_tools = driver.devtools  

dev_tools.create_session()  



# Enable console log capturing  

dev_tools.send_command("Log.enable")  



# Capture console logs  

logs = dev_tools.send_command("Log.entryAdded")  

for log in logs:  

    print(log)  



driver.get("https://example.com")  

driver.quit()

4. Performance Metrics Analysis

Capturing performance data such as page load time and network latency is crucial to identify bottlenecks in web application performance

from selenium import webdriver  



# Set up ChromeDriver and DevTools  

driver = webdriver.Chrome()  

dev_tools = driver.devtools  

dev_tools.create_session()  


# Enable performance monitoring  

dev_tools.send_command("Performance.enable")  



driver.get("https://example.com")  



# Retrieve performance metrics  

metrics = dev_tools.send_command("Performance.getMetrics")  

for metric in metrics["metrics"]:  

    print(f"{metric['name']}: {metric['value']}")  



driver.quit()

5. Device Emulation

Simulating mobile and tablet devices is necessary to test responsive web designs

from selenium import webdriver  



# Set up ChromeDriver and DevTools  

driver = webdriver.Chrome()  

dev_tools = driver.devtools  

dev_tools.create_session()  



# Enable device emulation  

mobile_emulation = {  

    "deviceMetrics": {"width": 375, "height": 667, "pixelRatio": 2.0},  

    "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"  

}  

dev_tools.send_command("Emulation.setDeviceMetricsOverride", mobile_emulation)  



driver.get("https://example.com")  

driver.quit()

Benefits of using Selenium DevTools

Selenium DevTools becomes useful when a test needs more than page-level actions. It gives you access to browser activity that can explain failures, reproduce edge cases, and improve the quality of technical checks.

  • Faster root-cause analysis: You can inspect failed requests, console errors, response codes, and browser events during the same test run. This helps you distinguish an application defect from a locator issue or timing problem.
  • Better control over test conditions: You can simulate slow networks, offline behaviour, custom geolocation, device metrics, or blocked resources without changing the application or external infrastructure.
  • More reliable testing of failure scenarios: CDP lets you mock responses or interrupt requests. You can test how the UI behaves when an API returns an error, a dependency is unavailable, or a resource takes longer than expected.
  • Stronger performance checks: You can collect network and browser performance data alongside functional tests. This makes it easier to spot slow resources, large payloads, and delays that a normal pass or fail result would miss.
  • Improved debugging for dynamic applications: Modern applications depend heavily on JavaScript and background API calls. DevTools gives you visibility into this activity, which is useful when the page state alone does not explain the result.
  • Greater value from an existing Selenium framework: Teams already using Selenium can add browser-level checks without replacing their main automation stack. WebDriver can continue to handle user flows while CDP supports targeted debugging, monitoring, and emulation.

Challenges in Selenium DevTools

The difficult part of Selenium DevTools is not enabling a CDP domain. Problems usually appear when tests collect asynchronous events, match the wrong request, retain browser state, or run against a different Chrome version.

1. CDP Events Cannot Be Called Like Commands

A CDP domain contains both commands and events. They are not interchangeable.

For example, this pattern is incorrect:

driver.execute_cdp_cmd("Log.enable", {})



# Incorrect: Log.entryAdded is an event

logs = driver.execute_cdp_cmd("Log.entryAdded", {})

Log.enable is a command. Log.entryAdded is an event emitted by the browser after a new log entry appears. Selenium’s execute_cdp_cmd() method can send commands, but it cannot by itself subscribe to bidirectional events.

For synchronous Python tests, ChromeDriver performance logs provide one practical way to collect Network and Page events:

import json

from selenium import webdriver




options = webdriver.ChromeOptions()

options.set_capability(

    "goog:loggingPrefs",

    {"performance": "ALL"}

)



driver = webdriver.Chrome(options=options)

driver.get("https://example.com")



for entry in driver.get_log("performance"):

    message = json.loads(entry["message"])["message"]



    if message["method"] == "Network.responseReceived":

        response = message["params"]["response"]



        print(response["status"], response["url"])



driver.quit()

Performance logging is not enabled by default. It must be configured when the browser session is created.

Tests that need continuous event listeners should use a listener-capable Selenium API instead of treating event names as commands.

2. Network Logs Can Match the Wrong Request

A single page action may trigger an OPTIONS request, the main API request, analytics calls, retries, and redirects. Matching only part of a URL can make the test validate the wrong response.

The safer approach is to connect each response to its original request through the CDP requestId:

import json

from urllib.parse import urlsplit




requests = {}

order_responses = []



for entry in driver.get_log("performance"):

    message = json.loads(entry["message"])["message"]

    method = message["method"]

    params = message["params"]



    if method == "Network.requestWillBeSent":

        request = params["request"]



        requests[params["requestId"]] = {

            "method": request["method"],

            "url": request["url"]

        }



    elif method == "Network.responseReceived":

        request_id = params["requestId"]

        original_request = requests.get(request_id)



        if not original_request:

            continue



        path = urlsplit(original_request["url"]).path



        if (

            original_request["method"] == "POST"

            and path == "/api/orders"

            and params["type"] in {"XHR", "Fetch"}

        ):

            order_responses.append({

                "status": params["response"]["status"],

                "url": params["response"]["url"]

            })



assert order_responses, "The order API request was not captured"

assert order_responses[-1]["status"] == 201

This prevents the test from confusing the real POST /api/orders request with a preflight request or another endpoint containing similar text.

3. Enabled Domains and Overrides Can Leak Between Tests

CDP settings belong to the current browser session. This matters when a framework reuses the same driver for several tests.

Suppose one test disables the browser cache:

driver.execute_cdp_cmd(

    "Network.setCacheDisabled",

    {"cacheDisabled": True}

)

A later performance test may then run without cache and report slower results, even though it never changed the cache setting itself.

Wrap temporary CDP changes in cleanup logic:

from contextlib import contextmanager




@contextmanager

def network_session(driver):

    driver.execute_cdp_cmd("Network.enable", {})



    try:

        yield

    finally:

        driver.execute_cdp_cmd(

            "Network.setCacheDisabled",

            {"cacheDisabled": False}

        )

        driver.execute_cdp_cmd("Network.disable", {})

Use the helper only around the test that needs network control:

with network_session(driver):

    driver.execute_cdp_cmd(

        "Network.setCacheDisabled",

        {"cacheDisabled": True}

    )



    driver.get("https://example.com")

Network.disable stops network tracking and prevents further Network events from being sent to the client.

The same cleanup rule applies to geolocation overrides, device metrics, extra headers, blocked URLs, and network conditions.

4. Browser Updates Can Break CDP Code Without Changing the Test

CDP was designed for browser debugging rather than as a stable test standard. Its commands, parameters, and generated Selenium APIs can differ between Chrome versions. Selenium advises keeping Chrome and the DevTools implementation aligned.

Record the browser and protocol details when a CDP test starts:

def get_cdp_environment(driver):

    capabilities = driver.capabilities

    protocol = driver.execute_cdp_cmd(

        "Browser.getVersion",

        {}

    )



    return {

        "browser": capabilities.get("browserName"),

        "browser_version": capabilities.get("browserVersion"),

        "chromedriver_version": capabilities

            .get("chrome", {})

            .get("chromedriverVersion", "unknown")

            .split(" ")[0],

        "protocol_version": protocol.get("protocolVersion"),

        "browser_product": protocol.get("product")

    }




environment = get_cdp_environment(driver)



for key, value in environment.items():

    print(f"{key}: {value}")

Add this output to CI failure reports. When a command suddenly returns an unknown-method or invalid-parameter error, you can check whether the browser, driver, or Selenium version changed before debugging the application.

5. Raw Performance Metrics Can Produce Misleading Assertions

Performance.getMetrics returns several browser-level measurements. Asserting every value makes tests sensitive to the machine, cache state, browser mode, and background workload.

Select only the metrics connected to the requirement:

driver.execute_cdp_cmd("Performance.enable", {})

driver.get("https://example.com")



result = driver.execute_cdp_cmd(

    "Performance.getMetrics",

    {}

)



metrics = {

    item["name"]: item["value"]

    for item in result["metrics"]

}



selected_metrics = {

    "TaskDuration": metrics.get("TaskDuration"),

    "ScriptDuration": metrics.get("ScriptDuration"),

    "JSHeapUsedSizeMB": (

        metrics.get("JSHeapUsedSize", 0) / 1024 / 1024

    )

}



print(selected_metrics)



driver.execute_cdp_cmd("Performance.disable", {})

Use these values for investigation or controlled regression checks. Do not treat them as a replacement for load testing or assume that a lower internal metric always means a faster user experience.

The safest framework design keeps CDP code behind small utilities. WebDriver should remain responsible for the user flow, while DevTools helpers handle specific tasks such as event capture, network inspection, and browser overrides.

Tips for integrating CDP effectively in existing Test Frameworks

Integrating CDP into your existing framework adds advanced capabilities, making your tests more reliable and efficient while ensuring ease of maintenance. Here’s how you can integrate Chrome DevTools Protocol (CDP) effectively into your existing test framework:

  1. Familiarise Yourself with CDP’s Key Features: Understand the essential features of CDP, like network interception, performance profiling, and device emulation. These will enhance your test scenarios when used properly.
  2. Combine CDP with Selenium WebDriver: Selenium 4 natively supports CDP. Integrate it into your current framework using the DevTools interface to interact with advanced browser features that were previously unavailable.
  3. Isolate CDP Logic: Keep CDP-specific logic separate within your test framework. By doing this, the core test scripts remain unaffected, and you can easily revert to standard Selenium WebDriver if needed.
  4. Start Small and Scale Up: Begin by using basic CDP features like network interception. Once you are comfortable, expand to more advanced capabilities like device emulation and performance profiling.
  5. Use CDP for Dynamic Content: Handle dynamic content more effectively with CDP. Features such as intercepting network requests or modifying responses can help manage dynamically loaded or AJAX-driven elements.
  6. Ensure Cross-Browser Compatibility: While CDP is typically used with Chrome, ensure compatibility with other browsers through cross-browser testing tools like BrowserStack. This will help keep tests consistent across different environments.
  7. Integrate CDP into CI/CD Pipelines: Automate your tests using CDP within your CI/CD pipelines. This ensures tests run smoothly at each stage of the development process, improving consistency.
  8. Monitor Performance: Use CDP’s performance profiling features to capture page load times, CPU usage, and memory consumption. This allows you to identify bottlenecks and optimise performance.
  9. Address Browser-Specific Issues: Keep in mind that CDP features may not work the same across all browser versions. Adapt your framework to handle any browser-specific quirks.
  10. Document Best Practices: Document the best practices for CDP usage within your team. This ensures a consistent approach, making the framework easier to maintain and scale.

Selenium DevTools vs. Puppeteer/Playwright

Here is a quick comparison between Selenium DevTools, Puppeteer, and Playwright for testing applications on Chrome browser:

FeatureSelenium DevToolsPuppeteerPlaywright
Browser SupportPrimarily supports Chrome/Chromium, but can be integrated into cross-browser testing with Selenium WebDriver.Supports Chrome/Chromium; can be extended to other browsers with extra setup.Supports Chrome, Chromium, Firefox, and WebKit (Safari).
Cross-Browser TestingSupports cross-browser testing through Selenium WebDriver, though DevTools itself is Chrome/Chromium-focused.Primarily for Chrome/Chromium; not designed for cross-browser testing.Ideal for cross-browser testing with seamless support for multiple browsers.
Network Interception & MockingStrong network interception and mocking capabilities via CDP, though less flexible than Puppeteer.Built-in network interception and mocking features.Advanced network mocking and interception, similar to Puppeteer.
Device EmulationSupports device emulation within Chrome/Chromium via DevTools, but not as extensive as Playwright.Excellent mobile device emulation features.Rich device emulation, supporting more devices and configurations out-of-the-box.
Performance MonitoringProvides performance metrics, resource tracking, and profiling, ideal for deep analysis.Limited performance monitoring features.Advanced performance analysis tools and tracing capabilities.
Ease of SetupSeamlessly integrates into existing Selenium frameworks for large-scale testing.Quick and easy to set up, but best for single-browser testing (Chrome/Chromium).Requires more setup but offers a powerful cross-browser testing suite.
Integration with Legacy SystemsBest for teams already using Selenium, offering advanced features without the need to switch tools.Does not integrate easily with Selenium or other frameworks.Good for teams starting fresh but lacks simple integration with legacy systems.

Selenium DevTools can be integrated into existing Selenium frameworks, which already support cross-browser testing, making it ideal when you need to test across different browser types. For teams already using Selenium, adding DevTools integration provides enhanced features without needing to switch to a new tool.

When handling advanced network operations or complex browser interactions, Selenium DevTools provides flexibility and detailed control over the browser’s internals, making it the better choice for specific scenarios like simulating network conditions, bypassing bot protections, or working with Cloudflare.

Practical Uses of Selenium DevTools

Selenium DevTools earns its place when the DOM cannot explain a test result. A failed assertion may come from an API error, a JavaScript exception, lost connectivity, or extra work on the browser’s main thread. The following scenarios use browser data to investigate or validate those conditions.

1. Debugging Flaky Tests with Browser and Network Evidence

A timeout only tells you that the expected element did not appear. It does not tell you whether the API returned 500, a script failed, or Chrome could not load a required resource.

Instead of collecting every log during every successful test, capture browser and network evidence when a test fails.

Performance logging must be enabled when ChromeDriver creates the session. It provides CDP events from the Network and Page domains.

import json



from selenium import webdriver

from selenium.common.exceptions import TimeoutException

from selenium.webdriver.common.by import By

from selenium.webdriver.support import expected_conditions as EC

from selenium.webdriver.support.ui import WebDriverWait




options = webdriver.ChromeOptions()

options.set_capability(

    "goog:loggingPrefs",

    {

        "browser": "ALL",

        "performance": "ALL"

    }

)



driver = webdriver.Chrome(options=options)

The following helper extracts JavaScript errors, failed network loads, and HTTP error responses:

def collect_failure_evidence(driver):

    console_errors = [

        {

            "level": entry["level"],

            "message": entry["message"]

        }

        for entry in driver.get_log("browser")

        if entry["level"] == "SEVERE"

    ]



    network_errors = []



    for entry in driver.get_log("performance"):

        message = json.loads(entry["message"])["message"]

        method = message["method"]

        params = message.get("params", {})



        if method == "Network.responseReceived":

            response = params["response"]



            if response["status"] >= 400:

                network_errors.append({

                    "type": "HTTP error",

                    "status": response["status"],

                    "url": response["url"]

                })



        elif method == "Network.loadingFailed":

            network_errors.append({

                "type": "Load failure",

                "error": params.get("errorText"),

                "resource": params.get("type")

            })



    return {

        "console_errors": console_errors,

        "network_errors": network_errors

    }

Call the helper only after the user flow fails:

driver.get("https://example.com/login")



driver.find_element(By.ID, "email").send_keys("user@example.com")

driver.find_element(By.ID, "password").send_keys("password")

driver.find_element(By.ID, "sign-in").click()



try:

    WebDriverWait(driver, 10).until(

        EC.visibility_of_element_located((By.ID, "dashboard"))

    )



except TimeoutException as error:

    evidence = collect_failure_evidence(driver)



    raise AssertionError(

        "Dashboard did not load.\n"

        + json.dumps(evidence, indent=2)

    ) from error

The failure report now shows more than a missing dashboard. It may reveal that /api/login returned 503 or that a JavaScript exception stopped the redirect.

Keep the network filter narrow in production frameworks. Capturing every request can expose tokens, cookies, and large response payloads in CI logs.

2. Testing Offline Behaviour and Recovery

Offline testing should cover more than the appearance of an error message. You also need to check whether the application preserves unsaved data and recovers after connectivity returns.

Current CDP versions recommend using Network.emulateNetworkConditionsByRule with Network.overrideNetworkState. The older Network.emulateNetworkConditions command is deprecated. The newer commands are still marked experimental, so this logic should remain inside a version-controlled helper.

def set_network_state(driver, offline):

    throughput = 0 if offline else -1

    connection = "none" if offline else "wifi"



    driver.execute_cdp_cmd(

        "Network.overrideNetworkState",

        {

            "offline": offline,

            "latency": 0,

            "downloadThroughput": throughput,

            "uploadThroughput": throughput,

            "connectionType": connection

        }

    )



    driver.execute_cdp_cmd(

        "Network.emulateNetworkConditionsByRule",

        {

            "matchedNetworkConditions": [

                {

                    "urlPattern": "",

                    "offline": offline,

                    "latency": 0,

                    "downloadThroughput": throughput,

                    "uploadThroughput": throughput,

                    "connectionType": connection,

                    "packetLoss": 0,

                    "packetQueueLength": 0,

                    "packetReordering": False

                }

            ]

        }

    )

You can now test an offline save and retry flow:

driver.execute_cdp_cmd("Network.enable", {})

driver.get("https://example.com/profile")



try:

    driver.find_element(By.ID, "display-name").clear()

    driver.find_element(By.ID, "display-name").send_keys("Updated Name")



    set_network_state(driver, offline=True)

    driver.find_element(By.ID, "save-profile").click()



    offline_message = WebDriverWait(driver, 5).until(

        EC.visibility_of_element_located((By.ID, "offline-message"))

    )



    assert "connection" in offline_message.text.lower()



    # The entered value should remain available for another attempt.

    assert (

        driver.find_element(By.ID, "display-name")

        .get_attribute("value")

        == "Updated Name"

    )



    set_network_state(driver, offline=False)

    driver.find_element(By.ID, "retry-save").click()



    WebDriverWait(driver, 10).until(

        EC.text_to_be_present_in_element(

            (By.ID, "save-status"),

            "Saved"

        )

    )



finally:

    set_network_state(driver, offline=False)

    driver.execute_cdp_cmd("Network.disable", {})

This test checks three separate behaviours:

  • The application detects the failed request.
  • User input survives the failure.
  • The operation succeeds after the connection returns.

You can extend the same pattern to shopping carts, draft forms, queued uploads, and applications that use service workers.

3. Detecting Performance Regressions in Critical Flows

Performance.getMetrics returns browser-level measurements such as script execution time, task duration, DOM node count, and JavaScript heap usage. Selenium exposes raw CDP commands through execute_cdp_cmd().

The values are cumulative within the browser session. An assertion against the final value alone can therefore include work from login, test setup, and previous page loads.

Take one measurement before the action and another after it:

TRACKED_METRICS = {

    "TaskDuration",

    "ScriptDuration",

    "LayoutDuration",

    "RecalcStyleDuration",

    "JSHeapUsedSize"

}




def read_performance_metrics(driver):

    result = driver.execute_cdp_cmd(

        "Performance.getMetrics",

        {}

    )



    return {

        metric["name"]: metric["value"]

        for metric in result["metrics"]

        if metric["name"] in TRACKED_METRICS

    }

The following example measures the work triggered when a user opens a large report:

driver.execute_cdp_cmd("Performance.enable", {})

driver.get("https://example.com/reports")



before = read_performance_metrics(driver)



driver.find_element(By.ID, "open-sales-report").click()



WebDriverWait(driver, 15).until(

    EC.visibility_of_element_located((By.ID, "sales-report-table"))

)



after = read_performance_metrics(driver)



duration_deltas = {

    name: after.get(name, 0) - before.get(name, 0)

    for name in {

        "TaskDuration",

        "ScriptDuration",

        "LayoutDuration",

        "RecalcStyleDuration"

    }

}



heap_growth_mb = (

    after.get("JSHeapUsedSize", 0)

    - before.get("JSHeapUsedSize", 0)

) / (1024 * 1024)



print("Duration deltas:", duration_deltas)

print(f"Heap growth: {heap_growth_mb:.2f} MB")



driver.execute_cdp_cmd("Performance.disable", {})

A large increase in ScriptDuration points towards expensive JavaScript work. Higher LayoutDuration or RecalcStyleDuration can indicate repeated layout calculations after the report appears. Heap growth becomes more useful when the same action is repeated several times and memory does not return to an expected range.

Do not copy one threshold across local machines and CI workers. Establish a baseline in a controlled environment first. Run a warm-up iteration and compare the same browser version, hardware class, cache state, and browser mode.

These checks are best used as focused regression guards. They do not replace load testing because they measure work inside one browser session rather than system behaviour under concurrent traffic.

Conclusion

Selenium DevTools extends WebDriver where page-level checks are not enough. It helps you inspect network activity, capture browser errors, emulate conditions, and collect performance data without replacing the user flows already handled by Selenium.

Use CDP only for cases that need browser-level access. Keep the logic in separate helpers, record browser and protocol versions in CI, and clean up temporary overrides after each test. This keeps the framework easier to maintain as browser behaviour and Selenium support evolve.

Version History

  1. Aug 07, 2026 Current Version

    Reworked the weaker sections with browser-level scenarios, code-backed explanations, and clearer guidance for using Selenium DevTools in real test frameworks.

    Ashwani Pathak
    Reviewed by Ashwani Pathak Automation Expert
Tags
Automation Testing Selenium Website Testing
Sujay Sawant
Sujay Sawant

Lead Engineer

Sujay Sawant is a Lead Solutions Engineer with 11+ years of experience in software testing, test automation, and customer engineering. He writes about automation frameworks, QA best practices, and practical testing approaches that help teams improve test coverage and release reliability.

Advanced Chrome Tests Hard to Scale?
Run Selenium DevTools tests on a cloud Selenium Grid with real browsers.