How to Upgrade from Selenium 3 to Selenium 4
Upgrade Selenium 3 safely: update your binding, check W3C capabilities and language-specific API changes, then run your browser test suite.
For many projects, upgrading from Selenium 3 to Selenium 4 starts with updating the Selenium binding dependency. Then confirm that your capabilities use the W3C WebDriver format, fix language-specific API changes and deprecated or internal API use, and run the suite across your supported browsers and environments. Selenium says W3C-compliant code from late Selenium 3 should work as expected in Selenium 4, but changing the dependency alone does not prove the migration is complete.
The Selenium downloads page lists version 4.49.0 as stable for its language bindings and Grid as of September 9, 2026. Releases continue to change, so check the current downloads page and the release notes for your selected version when you upgrade.
1. Record the current setup
Before changing versions, note the details that determine how your tests start and run. This gives you a useful baseline when a test fails after the upgrade.
- Selenium binding and exact version.
- Language runtime and version.
- Browser names and versions used locally and in CI.
- How each driver executable is installed or discovered.
- Whether tests use local drivers, Selenium Grid, or a cloud provider.
- Capabilities and provider-specific options sent when a session starts.
- Any code that uses deprecated Selenium APIs or internal packages.
2. Update the binding dependency
Use your project’s normal package manager and version policy. The examples below install the current version identified in the research snapshot; check the official downloads page before using that pin.
Java with Maven
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.49.0</version>
</dependency>
Python
python -m pip install --upgrade "selenium==4.49.0"
C# with .NET CLI
dotnet add package Selenium.WebDriver --version 4.49.0
Ruby
gem install selenium-webdriver -v 4.49.0
JavaScript with npm
npm install selenium-webdriver@4.49.0
These commands illustrate dependency updates; follow the package manager and lockfile workflow already used by your repository. The migration guide contains examples with older Selenium 4 versions. Do not treat those historical pins as current recommendations.
3. Check W3C capabilities
Selenium 4 uses the W3C WebDriver protocol and removed the legacy JSON Wire Protocol. Review the capabilities passed to the browser or remote provider, especially if session creation fails after the binding update.
| Use this W3C capability | Legacy name to replace |
|---|---|
browserVersion |
version |
platformName |
platform |
browserName |
Use the standard browser capability rather than a legacy or provider-specific substitute. |
acceptInsecureCerts |
Use the standard W3C spelling. |
pageLoadStrategy |
Use the standard W3C spelling. |
proxy, timeouts, unhandledPromptBehavior |
Use the standard W3C capability structure. |
Cloud and browser-vendor options are not all interchangeable. Keep provider-specific values under the vendor’s required prefixed key, such as a provider-defined options block, and check that provider’s current documentation for the exact prefix and nesting. Do not assume a generic example matches your service.
4. Fix binding-specific API changes
Compile or run a small representative test after the dependency update. Address errors using the migration guide for your binding and the API reference for your target release. These common changes are examples; they are not a complete list of changes in every Selenium 4 release.
Java: use Duration for timeouts and waits
Timeout and wait APIs use Duration instead of a number plus TimeUnit.
import java.time.Duration;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
When merging Firefox options and capabilities, assign the merge result instead of assuming the original options object was changed:
FirefoxOptions options = new FirefoxOptions();
options = options.merge(capabilities);
Legacy Firefox mode is deprecated, and BrowserType is deprecated in favor of Browser. Check compiler warnings and the target version’s API documentation before replacing code.
Python: use a Service object
Replace the old executable_path driver-construction argument with a Service object, or make the driver executable available on PATH.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
service = Service("/path/to/chromedriver")
driver = webdriver.Chrome(service=service)
try:
driver.get("https://example.com")
print(driver.title)
finally:
driver.quit()
C#: use AddAdditionalOption
Where the older options code uses the deprecated AddAdditionalCapability, use AddAdditionalOption for the demonstrated options case.
using OpenQA.Selenium.Chrome;
var options = new ChromeOptions();
options.AddAdditionalOption("someOption", "someValue");
Confirm the option name, value type, and whether it is standard or provider-specific before using it. The snippet shows the API shape, not a universal browser capability.
Ruby and JavaScript: update and resolve runtime errors
The migration guide’s basic Ruby and JavaScript steps update the selenium-webdriver gem or npm package. Run the project build and a small browser test after the update, then use the errors and deprecation messages to find code that needs adjustment for your target binding version.
5. Validate driver management
Selenium Manager is bundled with Selenium releases from 4.6 onward. When a driver is not already available, Selenium bindings use it as a fallback to help manage the driver. You can also keep manual driver installation through PATH or system properties, or continue with a third-party driver manager.
| Approach | What to verify |
|---|---|
| Selenium Manager fallback | Run in a clean local and CI environment; check that the required browser and driver can be resolved there. |
| Manual provisioning | Confirm the configured path exists, the executable has permission to run, and the driver matches the browser version used by the job. |
| Third-party manager | Check that it supports the binding and runtime you upgraded, and that CI uses the intended manager configuration. |
Migration does not require changing a working driver strategy. Validate it under the same local, container, and CI conditions where the suite is expected to run. If browser versions are pinned, keep that policy consistent; if they move, make the browser and driver resolution path part of the upgrade check.
6. Run the suite and review the target release
- Build or compile the project and fix binding-level errors.
- Run a short test that launches a browser, navigates, finds an element, and quits cleanly.
- Run tests that use remote sessions or cloud capabilities, if applicable.
- Run the full suite across the supported browser and runtime matrix.
- Review deprecation warnings and the release notes for the exact Selenium version selected.
Selenium 4 is not one frozen API surface. For example, Selenium 4.49.0 removed a deprecated Java file endpoint. Confirm release-specific changes before you upgrade, particularly if your project relies on older APIs or Selenium internals.
7. Optional Selenium 4 feature: relative locators
Relative locators find an element by its position relative to a known element, such as above, below, or beside it. Selenium uses browser geometry to determine element position and size. This is an optional capability to consider after the existing suite passes; it is not a migration requirement. See Selenium’s locator strategies documentation.
Common upgrade errors and fixes
| Symptom | Likely cause | What to check or change |
|---|---|---|
| Session creation fails with an invalid or unrecognized capability | Legacy JSON Wire Protocol names or structure remain, or a vendor option is in the wrong place. | Use W3C names such as browserVersion and platformName. Check the remote provider’s exact vendor prefix and nesting. |
| Code no longer compiles around waits or timeouts | Java code still uses the old number-and-TimeUnit overloads. |
Use Duration with timeout and wait APIs, and consult the API reference for the selected version. |
Python reports an unexpected executable_path argument |
Driver construction still uses the old argument. | Construct a Service and pass it with service=, or put the executable on PATH. |
| C# warns about an additional capability method | The code uses the deprecated AddAdditionalCapability method in the options case covered by the guide. |
Use AddAdditionalOption and confirm the option is valid for the browser or provider. |
| Firefox options or browser types behave differently | Code relies on a deprecated API or ignores the result of FirefoxOptions.merge. |
Assign the merge result; review current guidance for legacy Firefox mode and BrowserType. |
| Driver is not found or session startup fails only in CI | Driver discovery differs between a developer machine and CI, or the browser/driver combination is unavailable there. | Check PATH, configured system properties, executable permissions, browser installation, network access needed by the selected manager, and CI-specific setup. |
| Tests compile but fail after the upgrade | The suite may depend on changed or deprecated behavior, internal APIs, capabilities, or environment assumptions. | Reduce to a representative failing test, inspect warnings and session logs, and compare the selected release’s migration guidance and release notes. |
Performance, reliability, and cost considerations
A binding upgrade does not by itself make browser tests faster. Keep the comparison fair when diagnosing runtime changes: use the same tests, browser versions, machine or CI runner, and parallelism. Separate time spent resolving a driver or creating a session from the test’s own browser interactions. For stability, test the same driver strategy and capability payload used by the full suite, then run across the supported matrix.
Selenium is open-source software; this migration guide identifies no Selenium license or plan price. Operational costs depend on your own browser infrastructure, CI, or any remote browser service you use. The research sources do not establish a general cost or performance winner among those choices.
Or skip the browser setup
If the task is taking a website screenshot rather than migrating a browser automation suite, ScreenshotNeo offers a one-request screenshot API and an MCP server for AI agents. Before a capture, it accepts cookie or consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets. Each of those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; the response identifies the page verdict and billing status in headers.
cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo also has an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. See the API documentation, visit ScreenshotNeo, or sign up free for 1,000 screenshots a month with no card.
FAQ
Is Selenium 4 a required rewrite?
No. Selenium says W3C-compliant code from late Selenium 3 should work as expected, though APIs and internal dependencies can still need attention.
Do I have to adopt relative locators?
No. They are an optional Selenium 4 feature.
Does upgrading mean I must stop installing drivers manually?
No. Selenium Manager is a fallback option from Selenium 4.6; manual and third-party driver management remain choices.
Should I upgrade to exactly 4.49.0?
Check the current downloads page and the release notes when you act. Version 4.49.0 is the stable version listed in this article’s research snapshot, not a permanent recommendation.


