PRACTICAL GUIDE / Selenium 3 to 4 migration

Migrate Selenium 3 Capabilities and Grid Configuration to Selenium 4

Migrate Selenium 3 suites to Selenium 4 with W3C capability names, typed browser options, side-by-side Grid rollout, compatibility checks, and rollback.

By The Testing AcademyUpdated July 11, 20269 min read
All field guides
In this guide12 sections
  1. Inventory Protocol Assumptions Before Editing
  2. Freeze a Behavioral Baseline
  3. Upgrade the Binding as a Compile-Time Change
  4. Replace Legacy Capability Names With W3C Intent
  5. Move Browser Settings Into Options Classes
  6. Validate alwaysMatch and firstMatch Semantics
  7. Deploy Grid 4 Beside Grid 3
  8. Canary the Real Browser Matrix
  9. Diagnose Failures by Negotiation Layer
  10. Make Rollback a Supported State
  11. Run the Migration Exit Checklist
  12. Retire the Legacy Path Decisively

What you will learn

  • Inventory Protocol Assumptions Before Editing
  • Freeze a Behavioral Baseline
  • Upgrade the Binding as a Compile-Time Change
  • Replace Legacy Capability Names With W3C Intent

A Selenium 3 to 4 migration is two changes that should not be debugged as one: client code must speak in W3C-compatible capabilities and current binding APIs, while Grid must move to a different deployment and configuration model. Upgrade both in one cutover and every session-creation failure has too many possible owners.

Start with an inventory, make capability intent explicit in code, prove the upgraded client against a controlled endpoint, then deploy Grid 4 beside Grid 3 and route a measured canary. The migration finishes only after browser matching, commands, parallel execution, artifacts, and cleanup all work through the new path.

Inventory Protocol Assumptions Before Editing

Search code, configuration, CI variables, and cloud-provider helpers for DesiredCapabilities, version, platform, raw browser preference maps, old locator convenience methods, hard-coded hub paths, and Grid 3 startup flags. Record which layer owns each value. A capability duplicated in a test, base class, and CI wrapper will otherwise survive the migration in one location.

The official Selenium 4 upgrade guide explains that Selenium 3 supported the W3C protocol alongside the legacy protocol, while Selenium 4 removes the legacy path. Suites already using the later Selenium 3 W3C behavior may move more easily, but capability and Actions assumptions still require inspection.

Animated field map

Selenium 3 to 4 Migration Flow

Inventory legacy assumptions, upgrade client dependencies, rewrite capability intent, roll out a separate Grid 4 path, and verify behavior before retirement.

  1. 01 / legacy inventory

    Legacy Suite Inventory

    Locate old APIs, capability names, Grid flags, providers, and browser lanes.

  2. 02 / dependency upgrade

    Dependency Upgrade

    Compile and test one binding upgrade without changing production routing.

  3. 03 / capability rewrite

    Options and Capability Rewrite

    Use standard W3C names, typed options, and vendor-prefixed extensions.

  4. 04 / grid rollout

    Grid 4 Rollout

    Deploy a coherent side-by-side topology and direct canary sessions to it.

  5. 05 / compatibility proof

    Compatibility Verification

    Prove matching, commands, parallelism, artifacts, cleanup, and rollback.

Freeze a Behavioral Baseline

Before changing dependencies, run a representative matrix on the old stack and retain test results, negotiated capabilities, session-creation errors, browser coverage, Grid queue observations, and cleanup evidence. The baseline is not a promise that old behavior is correct; it is a comparison point for locating changes.

Select canaries that exercise more than navigation. Include Actions, windows or frames, downloads where supported, alerts, file upload, JavaScript execution, explicit waits, and remote cleanup. Include parallel cases because a sequential smoke test cannot expose shared driver state or capacity mismatch.

Separate application failures from infrastructure failures in the baseline. A flaky assertion should not become proof that Grid 4 is incompatible. Fix or quarantine unstable canaries before they become release gates.

Upgrade the Binding as a Compile-Time Change

Upgrade one language binding in an isolated branch or CI lane and let compiler errors, deprecation messages, and test failures reveal legacy API use. Do not simultaneously redirect that lane to a new Grid. First prove that upgraded tests can run against a known endpoint; then change routing.

In Java, replace removed findElementBy... convenience methods with findElement(By...). In every binding, inspect timeouts, service construction, browser options, and Actions code rather than assuming only imports changed. The upgrade guide lists binding-specific dependency and API guidance; use the section for the language actually in the suite.

Keep dependency versions centralized in the build system. A transitive Selenium 3 artifact next to Selenium 4 modules can create classpath or runtime ambiguity even when source compilation succeeds. Record the resolved dependency graph as migration evidence.

Replace Legacy Capability Names With W3C Intent

Standard capability names include browserName, browserVersion, platformName, acceptInsecureCerts, pageLoadStrategy, proxy, timeouts, and unhandledPromptBehavior. The W3C WebDriver specification is the normative definition of session creation and capability processing. Non-standard capability names need a vendor prefix.

Legacy version and platform are not aliases to carry forward. Change them to browserVersion and platformName. Provider fields such as build and test name should be nested under the prefix documented by that provider, not sent as unprefixed top-level keys.

Java
// Selenium 3 style that needs migration.
DesiredCapabilities legacy = new DesiredCapabilities();
legacy.setCapability("browserName", "firefox");
legacy.setCapability("version", requestedBrowserVersion);
legacy.setCapability("platform", requestedPlatform);
legacy.setCapability("build", buildName);
legacy.setCapability("name", testName);
WebDriver oldDriver = new RemoteWebDriver(gridUrl, legacy);

// Selenium 4 style with typed options and a provider-prefixed extension.
FirefoxOptions options = new FirefoxOptions();
options.setBrowserVersion(requestedBrowserVersion);
options.setPlatformName(requestedPlatform);
options.setCapability(
    "cloud:options",
    Map.of("build", buildName, "name", testName));

WebDriver driver = new RemoteWebDriver(gridUrl, options);

cloud:options is an illustrative prefix; use the exact extension key from your provider. For local Grid, omit provider metadata unless your node stereotypes and tests intentionally use a custom prefixed capability.

Move Browser Settings Into Options Classes

ChromeOptions, FirefoxOptions, and other browser-specific options classes express the selected browser's settings and also satisfy the capabilities contract used by RemoteWebDriver. This removes the need to merge a generic desired-capabilities object with a separate options object.

Keep browser arguments, preferences, binary locations, and browser extensions inside the matching options class. Keep standard matching requirements on its standard setters. Put provider metadata in one documented vendor extension. This division makes failures easier to classify: browser startup settings belong to the options class, while Grid matching depends on the requested standard and custom capabilities.

Do not copy every capability returned by an old session into a new request. Returned capabilities include discovered facts and defaults; a request should contain only constraints and options the test actually needs. Over-constraining browserVersion or platformName can prevent Grid from finding otherwise acceptable slots.

Validate alwaysMatch and firstMatch Semantics

At the protocol level, alwaysMatch contains requirements shared by every candidate, while each firstMatch entry provides an alternative combined with those shared requirements. Do not duplicate the same capability name in both halves of a combination. Keep alternatives minimal so operators can explain which candidate matched.

JSON
{
  "capabilities": {
    "alwaysMatch": {
      "browserName": "firefox",
      "platformName": "linux"
    },
    "firstMatch": [
      {"browserVersion": "requested-stable"},
      {"browserVersion": "requested-preview"}
    ]
  }
}

Most test code should let the binding construct this payload through Options rather than posting JSON directly. The explicit form is useful when diagnosing Grid logs or provider requests. If every candidate fails, compare the resulting request with registered slot stereotypes and remove requirements that are not part of the test's purpose.

Deploy Grid 4 Beside Grid 3

Grid 4 can run as Standalone, Hub and Node, or fully distributed components. The Grid getting-started guide documents those roles and their startup commands. Treat Grid 4 as a separate topology with its own Router URL, Event Bus connectivity, registration, status, logs, and configuration.

Shell
# A disposable staging endpoint.
java -jar selenium-server.jar standalone --port 4444

# A Hub and a Node on separate hosts.
java -jar selenium-server.jar hub --port 4444
java -jar selenium-server.jar node \
  --hub http://grid-hub:4444 \
  --max-sessions 4

Use a pinned server artifact and reviewed TOML or CLI configuration in real deployment automation. Do not copy Grid 3 hub/node flags blindly. Confirm component reachability in both directions, declared external URLs, registration secrets, driver discovery, slot stereotypes, session timeout policy, and observability.

Run Grid 3 and Grid 4 side by side during validation. Route clients by an explicit environment URL. Do not attempt a mixed-major hub/node cluster; coherent topologies make rollback a routing change instead of an emergency rebuild.

Canary the Real Browser Matrix

Begin with one low-risk CI lane and one browser stereotype. Capture the new session request and returned capabilities, then verify that the actual browser and platform satisfy the test's intent. Expand by browser, platform, remote provider, and high-risk feature rather than by an arbitrary percentage alone.

Compare session admission, command behavior, failure classifications, artifacts, and quit() completion with the baseline. Grid 4's status and logs should show sessions on the expected nodes. A passing assertion on the wrong browser is a routing defect, not a successful canary.

Keep the old endpoint available until the new path survives representative parallel load. Rollback should change the suite's Router URL and dependency lane according to the compatibility plan; rehearse it before production traffic depends on it.

Diagnose Failures by Negotiation Layer

An immediate invalid-argument response at session creation points to malformed standard capabilities, unprefixed extensions, incompatible value types, or duplicate capability names. A session-not-created response with a valid payload may mean no registered stereotype matches, a browser cannot start, or Grid capacity is unavailable. Read both client and Grid evidence.

If local sessions work but remote sessions fail, compare the Options serialization and Grid stereotypes. If only provider sessions fail, verify the provider prefix and nested schema from that provider's current documentation. If commands fail after creation, inspect the specific API migration, especially Actions or removed convenience methods, rather than continuing to edit capabilities.

Grid nodes that never register indicate topology, network, event-bus, external-URL, secret, or startup configuration problems. They are independent of test locators and should be triaged before suite failures.

Make Rollback a Supported State

Side-by-side Grids cost temporary infrastructure, but they isolate protocol and topology variables and enable fast routing rollback. An in-place replacement is cheaper on paper yet leaves no clean comparison endpoint when matching fails.

Keeping dual client dependency lanes also costs CI time. Use it during migration, then remove the Selenium 3 lane once exit criteria are met. A permanent compatibility matrix becomes maintenance debt and can conceal which API is authoritative.

Avoid broad capability fallbacks that make any browser acceptable just to keep tests green. Flexible matching is useful only when the test genuinely supports each alternative and reports what it received.

Run the Migration Exit Checklist

  • Legacy capability names, raw provider fields, and removed APIs are inventoried.
  • A stable old-stack baseline covers commands, parallelism, artifacts, and cleanup.
  • The upgraded binding resolves without Selenium 3 modules or hidden wrappers.
  • Browser-specific settings use the correct Options class.
  • Standard requests use browserVersion and platformName where needed.
  • Every extension capability uses the provider's documented vendor prefix.
  • Grid 4 runs as a coherent side-by-side topology with verified registration.
  • Canary results confirm requested and returned capabilities match test intent.
  • Representative parallel runs leave no leaked sessions or unexplained queue growth.
  • Routing rollback and evidence retention have been exercised.

Retire the Legacy Path Decisively

Migration is complete when the code expresses W3C capability intent, Grid 4 consistently matches and executes the required browser matrix, and operators can diagnose or roll back the route. Remove old wrappers, flags, and compatibility branches after that proof. Leaving both models in the framework only postpones the next failure to a less convenient day.

// LIVE COURSE / THE TESTING ACADEMY

Playwright Automation Mastery

Go beyond Selenium. Master Playwright with JS/TS in 90 days.

From the instructor behind this guide.

Playwright jobs are growing 8x faster than Selenium. 90 days / 75+ live hrs / Tue-Thu-Sat 7 AM IST.

Code PROMODE / 10% offJoin the batch

The Testing Academy editorial desk

Practical QA guidance built around test evidence, production tradeoffs, and interview-ready explanations.

Published July 11, 2026 / Reviewed July 11, 2026

PRIMARY REFERENCES

Verify the details at the source

QABattle guides are practical explanations. Product behavior, standards, and APIs can change, so use these primary references for the canonical details.

  1. 01
    Selenium documentation

    Selenium Project

    Canonical WebDriver, Grid, waits, element, and browser automation guidance.

  2. 02
    WebDriver standard

    W3C

    The browser automation protocol specification behind WebDriver implementations.

FAQ / QUICK ANSWERS

Questions testers ask

Can Selenium 3 DesiredCapabilities be copied unchanged into Selenium 4?

Do not assume so. Replace legacy names such as version and platform, move browser settings into Options classes, and group provider metadata under the provider's vendor-prefixed key.

Should client bindings and Selenium Grid be upgraded at the same time?

Separate the changes. Make tests W3C-compliant and upgrade bindings first in a controlled lane, then validate them against a side-by-side Grid 4 deployment before routing broader traffic.

What replaces version and platform capabilities in Selenium 4?

Use the W3C standard names browserVersion and platformName. Use browser option classes for browser-specific settings and a vendor-prefixed extension capability for provider metadata.

Can Grid 3 nodes register with a Grid 4 Hub?

Do not design a mixed-major Grid. Run old and new Grid topologies side by side, direct canary clients explicitly, and replace components as a coherent deployment unit.

What proves a Selenium 4 migration is complete?

The suite compiles without legacy API use, requested capabilities negotiate as intended, representative browsers pass through Grid 4, parallel cleanup works, and rollback has been exercised.