ScreenshotNeo

BlogGuides

Selenium 4 New Features: What’s Changed for WebDriver Tests

Selenium 4 standardizes WebDriver, adds relative locators, rebuilds Grid, and continues to expand BiDi. Here’s what changes for your tests and what to check before upgrading.

By the ScreenshotNeo team4 October 202613 min read

Selenium 4 is a major release line, not a single fixed feature set. The original 4.0 release arrived on October 13, 2021. For most test suites, the first upgrade step is changing the Selenium dependency and resolving deprecated or internal API usage—not rewriting every test. The changes that matter most are W3C WebDriver alignment, optional relative locators, new browser-specific capabilities, a rebuilt Grid, Selenium Manager for driver setup, and the continuing addition of WebDriver BiDi support.

The right migration depends on what your suite uses. Existing CSS and XPath locators can stay. Local tests do not need Grid. BiDi commands and some extra capabilities must be checked against the browser, language binding, and Selenium version you actually run.

1. What changed, at a glance

Area What changed What it means for a test suite
WebDriver protocol Selenium 4 aligned around the W3C WebDriver standard. Greater protocol standardization; usually no visible rewrite to ordinary test steps.
Locators Relative locators can find elements by position in relation to another element. Use them selectively when a spatial relationship makes a test clearer.
Browser capabilities The 4.0 announcement highlighted additional capabilities for Firefox and Chromium-derived browsers. Check support for the specific browser and binding before relying on authentication, interception, DOM-change waits, or JavaScript error inspection.
Driver setup Selenium Manager was introduced to reduce manual driver configuration. Review its behavior in your current environment; the original 4.6 description is historical, not a full statement of current scope.
Grid Grid was rebuilt for standalone, hub-and-node, and distributed deployments. Useful for remote and parallel execution; optional for local runs.
Browser events WebDriver BiDi adds a WebSocket-based, bidirectional channel. Enables event-driven automation, but command support varies by browser, binding, and version.

2. Upgrading from Selenium 3

Selenium’s 4.0 launch guidance described upgrading as intended to be close to a dependency change. The same announcement cautioned that code using internal or deprecated APIs could encounter problems. Treat “drop-in” as the migration goal, not as a guarantee for every project. [Selenium 4 launch announcement]

A practical upgrade sequence

  1. Inventory your binding and runtime. Record the Selenium language binding, browser versions, operating system, driver installation method, and whether tests use a local driver or Selenium Server/Grid.
  2. Upgrade the binding in a branch. Follow the language-specific Selenium upgrade guidance and pin a deliberate dependency version for reproducible CI builds.
  3. Remove deprecated and internal API usage. Search for deprecated calls and references to implementation internals. Replace these before investigating failures that may be caused by unrelated browser or environment changes.
  4. Run a small representative test set. Include navigation, waits, frames/windows if used, and any browser-specific operations. Compare failures by category rather than changing all locators at once.
  5. Check driver resolution in the real environment. A developer laptop, container, and locked-down CI runner may have different browsers, PATH values, permissions, and network access.
  6. Only adopt new features where they solve a concrete problem. Relative locators, BiDi, and Grid are additions; an upgrade does not require using them.

Python: runnable local WebDriver example

Install the Selenium Python binding in the environment where the test will run:

python -m pip install selenium

Save as smoke_test.py. This example opens a page, waits for a known element, checks its text, and always closes the browser. Selenium Manager can assist with driver setup when needed, but the actual result depends on the installed Selenium version and environment.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


def main():
    options = webdriver.ChromeOptions()
    # Uncomment for a headless CI run:
    # options.add_argument("--headless=new")

    driver = webdriver.Chrome(options=options)
    try:
        driver.get("https://example.com")
        heading = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located((By.TAG_NAME, "h1"))
        )
        assert heading.text == "Example Domain", heading.text
        print(f"Page title: {driver.title}")
    finally:
        driver.quit()


if __name__ == "__main__":
    main()

Run it with python smoke_test.py. For Firefox, use webdriver.Firefox() and the matching Firefox options; for Edge, use webdriver.Edge(). Confirm the driver/browser behavior for the Selenium release and machine rather than assuming setup is identical across platforms.

Java: runnable local WebDriver example

With Selenium Java available on the classpath (for example, through your build tool), this standalone class exercises the same basic flow:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;

public class SmokeTest {
  public static void main(String[] args) {
    WebDriver driver = new ChromeDriver();
    try {
      driver.get("https://example.com");
      String heading = new WebDriverWait(driver, Duration.ofSeconds(10))
          .until(ExpectedConditions.visibilityOfElementLocated(By.tagName("h1")))
          .getText();
      if (!"Example Domain".equals(heading)) {
        throw new AssertionError("Unexpected heading: " + heading);
      }
      System.out.println("Page title: " + driver.getTitle());
    } finally {
      driver.quit();
    }
  }
}

3. W3C WebDriver alignment

WebDriver is the browser-control interface Selenium uses locally or through Selenium Server on a remote machine. Selenium’s current documentation describes WebDriver as a W3C Recommendation. Selenium 4’s alignment is best understood as protocol standardization and ecosystem interoperability; it does not mean every Selenium 3 test needs a new interaction style. [Selenium WebDriver documentation]

For ordinary commands such as finding an element, clicking it, entering text, and navigating, teams should first check whether their existing tests still work after upgrading the binding and environment. Most migration effort tends to come from deprecated APIs, changed dependency/runtime combinations, or driver and CI configuration—not from replacing every WebDriver call.

4. Relative locators

Relative locators find an element in relation to another element’s position: above, below, to the left, to the right, or near. They are useful when the page gives you a reliable anchor element and the relationship is meaningful. They complement CSS, ID, name, and XPath locators; they do not replace them.

Python example: find a field to the right of its label

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with


driver = webdriver.Chrome()
try:
    driver.get("https://example.com/form")
    label = driver.find_element(By.CSS_SELECTOR, "label[for='email']")
    email_input = driver.find_element(
        locate_with(By.TAG_NAME, "input").to_right_of(label)
    )
    email_input.send_keys("dev@example.com")
finally:
    driver.quit()

Use an actual page and anchor selector from your application in place of the illustrative URL and selectors. Keep a conventional locator when it expresses the element’s identity more reliably. A visual relationship can change with responsive layout, localization, inserted elements, or a redesigned form, so relative positioning is not automatically more robust than a direct selector.

Strategy Good fit Watch for
ID, name, CSS A stable, unique attribute or clear component selector. Selectors coupled to generated classes or implementation details.
XPath A relationship in the DOM tree is the clearest expression. Long expressions that depend on fragile page structure.
Relative locator A stable anchor plus a real spatial relationship. Layout shifts, responsive breakpoints, overlapping or repeated candidates.

5. Browser-specific capabilities

The original Selenium 4 announcement called out additional capabilities for Firefox and Chromium-derived browsers, including basic and digest authentication, network interception, waiting for a DOM change, and inspecting JavaScript errors. These were described for browser families; do not assume every capability works identically in every browser or binding. [Selenium 4 launch announcement]

Before making one of these capabilities part of a required test path, verify all four pieces: the Selenium binding version, browser version, browser driver or remote endpoint, and the exact API/command documented for that combination. If your test needs portable event observation across browsers, evaluate WebDriver BiDi support rather than treating a Chromium-specific DevTools feature as universal.

6. Selenium Manager and driver setup

Selenium Manager was introduced to reduce the repeated manual work of matching browser drivers to installed browsers. The Selenium Project’s initial 4.6 description said it could configure Chrome, Firefox, and Edge drivers when a driver was not found on PATH; if an installed driver was found, that behavior would be ignored. That was an introduction-era description, so consult current documentation for current behavior rather than treating the 2022 scope as exhaustive. [Selenium Manager introduction]

Does Selenium 4 still need a separate ChromeDriver? You may not need to download and configure it manually when Selenium Manager can resolve the driver for your environment. But do not infer that every runner can reach the required resources or has a compatible browser setup. Validate driver resolution in CI, containers, and restricted networks; for tightly controlled builds, teams may choose explicit browser and driver provisioning for repeatability.

  • Check browser availability and version on the runner.
  • Check PATH and any explicitly configured driver locations.
  • Check outbound network policy, proxy settings, filesystem permissions, and container user.
  • Log the Selenium and browser versions when a session fails to start.
  • Decide whether automatic resolution or a pinned image/driver is the reproducible option for your deployment.

7. WebDriver BiDi and CDP

WebDriver BiDi adds a WebSocket-based, bidirectional connection so automation can subscribe to and react to browser events such as network activity, console messages, and JavaScript errors. Traditional WebDriver interactions are mostly command/response; BiDi adds event-driven communication. Selenium’s documentation positions BiDi as the standards-based, cross-browser direction, while the Chrome DevTools Protocol (CDP) remains Chromium-specific. [Selenium BiDi documentation]

BiDi is not a synonym for CDP. CDP can expose Chromium development features, but it is not the cross-browser W3C protocol. BiDi implementation is evolving across Selenium bindings and browsers. Selenium 4.47 and 4.49 release announcements describe ongoing binding work; their notes do not establish that every BiDi command is supported everywhere. Verify the specific command in the release notes and documentation for your language binding and target browser before designing a critical test around it. [Selenium release announcements]

When to consider BiDi

  • You need browser events, such as observing console output or network activity, rather than only issuing clicks and navigation commands.
  • You want a standards-oriented path for event-driven browser automation across browser vendors.
  • Your browser and Selenium binding implement the command you need, and the support level is acceptable for your suite.

Keep ordinary WebDriver commands for ordinary interactions. Use CDP only when you specifically need a Chromium development capability and accept the portability trade-off. Use BiDi when its current implementation supports the event or command your test requires.

8. Selenium Grid 4: what changed for execution

Grid 4 was rebuilt to support standalone operation, traditional hub-and-node setups, and distributed deployments intended for modern infrastructure such as Kubernetes. The launch material also described Docker container management, a refreshed UI with a GraphQL model, live VNC session previews, and OpenTelemetry support. These are operational features for remote sessions, parallel execution, and visibility. A local test does not need Grid simply because it uses Selenium 4. [Selenium 4 launch announcement]

Topology Use it when Trade-off
Local WebDriver A developer machine or single runner is enough. Browser capacity and environment are tied to that machine.
Standalone Grid You want a Selenium Server endpoint while keeping deployment simple. Still need to provision and monitor the server and browser capacity.
Hub and nodes You want a central Grid coordinating separate browser hosts. More services and network/configuration points to maintain.
Distributed deployment Capacity and operations require deployment across infrastructure such as Kubernetes. Highest operational complexity; needs appropriate observability and capacity management.

The Selenium Server JAR CLI also provides help and configuration inspection facilities described in the Selenium 4 tour, including info topics and --dump-config for emitting active configuration as JSON. CLI details can change; confirm syntax against the server version you run. [A Tour of 4: New Commands]

9. A migration decision checklist

  • Have you upgraded the binding and checked the migration guidance for that language?
  • Does the suite depend on deprecated methods, internals, or old capabilities?
  • Do existing CSS/XPath locators still express the target more directly than a relative locator?
  • Have you verified browser-specific capabilities against the target browser and binding?
  • Does the suite need local execution, remote sessions, or parallel Grid capacity?
  • Does driver resolution work with the actual browser, PATH, permissions, and network policy in CI?
  • For BiDi, have you confirmed the command is available in your exact Selenium binding/browser combination?
  • Are browser, Selenium, and infrastructure versions recorded so failures can be reproduced?

10. Troubleshooting common upgrade problems

Symptom Likely cause What to check or change
Compilation or import errors after dependency upgrade Deprecated API removal, package changes, or reliance on internal classes. Use the binding’s migration guidance; replace internal/deprecated calls with supported public APIs.
Session fails before the browser opens Browser/driver mismatch, driver resolution failure, unsupported environment, permissions, or network restrictions. Record versions; inspect PATH, browser install, network/proxy access and filesystem permissions; validate Selenium Manager in that runner.
Works locally but fails in CI Different browser, operating system, display/headless configuration, user permissions, or network access. Align runtime and browser provisioning; use explicit headless configuration where needed; capture session startup logs.
Relative locator finds the wrong element More than one element satisfies the spatial relationship, or layout shifted. Use a stronger anchor or constrain by component; use a stable direct locator if position is not an invariant.
Browser feature method is unavailable or behaves differently The feature is browser-, binding-, or version-specific. Check support for the exact browser and binding; do not assume a Firefox capability maps to Chromium or vice versa.
BiDi subscription or command fails Command not implemented for that browser/binding/version, or session setup does not enable the needed capability. Check current BiDi documentation and release notes for the exact combination; reduce the test to a supported event/API.
Remote Grid session cannot be created Grid topology, endpoint, node availability, browser capability, or network configuration is wrong. Inspect active Grid configuration, endpoint reachability and node/browser availability; use server CLI help for the deployed version.
Tests become flaky after changing locators or waits Timing or layout assumptions were introduced during migration. Prefer explicit conditions for the state needed; avoid fixed sleeps as a substitute for waiting on a meaningful condition.

11. Performance, reliability, and cost considerations

Performance

Selenium 4’s feature list is not a performance guarantee. The biggest practical execution choices are usually where browsers run, how many sessions the infrastructure can support, and how much work each test performs. Grid enables remote and parallel execution, but parallelism is useful only when the runner and application can handle the added load. Relative locators do not inherently make tests faster; choose locators for clear, stable intent.

Reliability

Pin and record the Selenium binding and browser environment where reproducibility matters. Validate Selenium Manager and browser-specific capabilities in the same environment used by CI. Treat layout relationships as assumptions that need validation, and treat BiDi support as version-sensitive. A Grid deployment adds network and service dependencies, so include its health and browser-node availability in failure diagnosis.

Cost

The Selenium libraries do not determine the total cost of running browser tests. Account for the machines or hosted browser capacity, parallel workers, CI time, and maintenance effort needed for drivers, browsers, and Grid. Use local execution for a small suite when it meets the need; introduce Grid when remote capacity or parallel execution justifies the operational overhead.

12. Capture screenshots of pages without managing a browser

For visual checks or saved page artifacts, you can run the browser yourself with Selenium and capture a screenshot using the driver’s screenshot API. That keeps capture inside your test flow, but you own browser setup, page readiness, and any cleanup required for a clear image. If you need a screenshot rather than an interactive WebDriver session, ScreenshotNeo is a website screenshot API and MCP server for developers. It returns an image or PDF from one GET request.

DIY Selenium screenshot

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


driver = webdriver.Chrome()
try:
    driver.set_window_size(1440, 1000)
    driver.get("https://example.com")
    WebDriverWait(driver, 10).until(
        EC.title_contains("Example")
    )
    driver.save_screenshot("page.png")
finally:
    driver.quit()

This captures the current viewport. For full-page capture, behavior varies by browser and driver; do not assume save_screenshot captures content beyond the viewport. You may need a browser-specific technique or a dedicated capture tool. Make the readiness condition match the page you are testing, and avoid capturing before asynchronous content appears.

Or skip the browser setup

Use ScreenshotNeo when you want a screenshot or PDF without managing a WebDriver session. The options include full-page capture with lazy images loaded, element capture by CSS selector, device presets and custom viewport sizes, dark mode, custom CSS/JavaScript, wait conditions, request blocking, cookies and headers, image formats, caching, async jobs, and bulk capture. See the ScreenshotNeo API documentation for parameters.

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

ScreenshotNeo accepts cookie/consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card required.

13. FAQ

Do I need to rewrite Selenium 3 tests to upgrade?

Usually not as a starting assumption. Upgrade the binding, resolve deprecated or internal API usage, and run representative tests. The Selenium 4 launch described the change as intended to be a dependency-level upgrade but warned about deprecated and internal APIs.

Are relative locators required in Selenium 4?

No. They are an optional locator strategy for relationships such as “to the right of” or “above.”

Does Selenium 4 require Selenium Grid?

No. Grid is for remote and distributed browser execution. A local WebDriver session remains appropriate when it meets the suite’s needs.

Is BiDi the same as CDP?

No. BiDi is the standards-based bidirectional WebDriver protocol; CDP is Chromium-specific.

Does every browser support every Selenium 4 feature?

No. Confirm the feature with the target browser, Selenium binding, and version before depending on it.

Primary references