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.
In this guide12 sections
- Inventory Protocol Assumptions Before Editing
- Freeze a Behavioral Baseline
- Upgrade the Binding as a Compile-Time Change
- Replace Legacy Capability Names With W3C Intent
- Move Browser Settings Into Options Classes
- Validate alwaysMatch and firstMatch Semantics
- Deploy Grid 4 Beside Grid 3
- Canary the Real Browser Matrix
- Diagnose Failures by Negotiation Layer
- Make Rollback a Supported State
- Run the Migration Exit Checklist
- 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.
01 / legacy inventory
Legacy Suite Inventory
Locate old APIs, capability names, Grid flags, providers, and browser lanes.
02 / dependency upgrade
Dependency Upgrade
Compile and test one binding upgrade without changing production routing.
03 / capability rewrite
Options and Capability Rewrite
Use standard W3C names, typed options, and vendor-prefixed extensions.
04 / grid rollout
Grid 4 Rollout
Deploy a coherent side-by-side topology and direct canary sessions to it.
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.
// 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.
{
"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.
# 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 4Use 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
browserVersionandplatformNamewhere 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.
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.
- 01Selenium documentation
Selenium Project
Canonical WebDriver, Grid, waits, element, and browser automation guidance.
- 02WebDriver 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.
RELATED GUIDES
Continue the learning route
GUIDE 01
WebDriver Capability Negotiation with alwaysMatch and firstMatch
Understand WebDriver capability negotiation with alwaysMatch, firstMatch, Selenium RemoteWebDriver, conflict rules, and session evidence.
GUIDE 02
Designing a Cross-Browser Options Matrix in Selenium WebDriver 4
Design a Selenium browser options matrix that separates W3C capabilities, vendor settings, environments, and verified cross-browser expectations.
GUIDE 03
Selenium Grid Tutorial: Run Tests Across Browsers
Selenium Grid tutorial explaining architecture, setup, remote WebDriver, browser capabilities, parallel execution, Docker, CI, and debugging tips.
GUIDE 04
Migrate Selenium CDP Hooks to WebDriver BiDi
Migrate Selenium CDP hooks to WebDriver BiDi with a capability inventory, event adapters, parity tests, cross-browser rollout, and failure diagnostics.