How To Upgrade to Selenium 4

Sauce AI for Test Authoring: Move from intent to execution in second.|xBack to ResourcesBlogPosted October 12, 2021

How To Upgrade to Selenium 4

The Selenium squad has spent a full amount of clip making the upgrade process as painless as potential. A few things have been deprecated, so you might hit a couple of issues while upgrading, especially if you have progress usance functionality in your testing framework. This usher will show you how to move from Selenium 3 to Selenium 4.

quote

Upgrading to Selenium 4 should be a painless process if you are using one of the officially supported speech (Ruby, JavaScript, C #, Python, and Java). There might be some example where a few issues can happen, and this guide will facilitate you to sort them out. We will go through the steps to upgrade your undertaking dependencies and understand the major deprecations and change the new version upgrade brings.

Note: while Selenium 3.x versions were be germinate, support for the W3C WebDriver touchstone was implemented. Both this new protocol and the legacy JSON Wire Protocol was supported. Around version 3.11, Selenium code become compliant with the Level 1 W3C Recommendation. W3C compliant code in the latest version of Selenium 3 will work as expected in Selenium 4.

Preparing our test codification

Selenium 4 remove support for the bequest protocol and uses the W3C WebDriver criterion by default under the tough. For most things, this effectuation will not involve end users. The major elision are Capabilities and the Actions class.

Capabilities

If the test capabilities are not structured to be W3C compliant, may make a session to not be started. Here is the list of W3C WebDriver standard capacity:

browserName
browserVersion (replaces version)
platformName (replaces platform)
acceptInsecureCerts
pageLoadStrategy
proxy
timeouts
unhandledPromptBehavior

An up-to-date tilt of standard capacity can be found atW3C WebDriver.

Any capability that is not contained in the tilt above, needs to include a vendor prefix. This hold to browser specific capabilities as well as. For example, if we use the build and name capability in our tests, we need to enclose them in a sauce: alternative block (a consummate example is demonstrate below).

From DesiredCapabilities to Browser Options

The use of browser Options rather of stable browser methods of DesiredCapabilities has been suggest since Selenium 3.8. Those static methods experience been withdraw in Selenium 4. This means that DesiredCapabilities.chrome () or DesiredCapabilities.firefox () and similar are not present anymore. See the examples below to transmigrate from those static methods to browser Options.

For example:

1
DesiredCapabilities caps =DesiredCapabilities.chrome();
2
DesiredCapabilities caps =DesiredCapabilities.edge();
3
DesiredCapabilities caps =DesiredCapabilities.firefox();
4
DesiredCapabilities caps =DesiredCapabilities.internetExplorer();
5
DesiredCapabilities caps =DesiredCapabilities.safari();
6
7
// Are replaced by:
8
9
ChromeOptionsbrowserOptions=newChromeOptions();
10
EdgeOptionsbrowserOptions=newEdgeOptions();
11
FirefoxOptionsbrowserOptions=newFirefoxOptions();
12
InternetExplorerOptionsbrowserOptions=newInternetExplorerOptions();
13
SafariOptionsbrowserOptions=newSafariOptions();
14

Using browserOptionssimplifies the configuration take to start a new session, allows setting browser-specific background (like headless in Chrome), and trim the chances of browser misconfiguration.

A complete illustration

Following, we can see a codification block with the old exercise of capability names and DesiredCapabilities. Followed by a block that demo how the code postulate to be updated.

The representative is shown in the different functionary languages supported by Selenium. When browser Options are preferred when uncommitted, platform and version are replaced by platformName and browserVersion, and Sauce Labs specific capabilities are placed inside a sauce: options cube.

Java

1
DesiredCapabilities caps = DesiredCapabilities.chrome ();
2
DesiredCapabilities caps = DesiredCapabilities.edge ();
3
DesiredCapabilities caps = DesiredCapabilities.firefox ();
4
DesiredCapabilities caps = DesiredCapabilities.internetExplorer ();
5
DesiredCapabilities cap = DesiredCapabilities.safari ();
6
7
// Are replace by:
8
9
ChromeOptions browserOptions = new ChromeOptions ();
10
EdgeOptions browserOptions = new EdgeOptions ();
11
FirefoxOptions browserOptions = new FirefoxOptions ();
12
InternetExplorerOptions browserOptions = new InternetExplorerOptions ();
13
SafariOptions browserOptions = new SafariOptions ();
14

JavaScript

1
// Before:
2
3
caps ={};
4
caps[& # x27; browserName & # x27;]=& # x27; Firefox & # x27;;
5
caps[& # x27; platform & # x27;]=& # x27; Windows 10 & # x27;;
6
caps[& # x27; version & # x27;]=& # x27; 92 & # x27;;
7
caps[& # x27; build & # x27;]=myTestBuild;
8
caps[& # x27; name & # x27;]=myTestName;
9
10
//After:
11
12
capableness={
13
browserName:& # x27; firefox & # x27;,
14
browserVersion:& # x27; 92 & # x27;,
15
platformName:& # x27; Windows 10 & # x27;,
16
& # x27; sauce: selection & # x27;:{
17
build:myTestBuild,
18
name:myTestName,
19
}
20
}
21

C#

1
// Before:
2
3
DesiredCapabilities crest = new DesiredCapabilities ();
4
caps.SetCapability (& quot; browserName & quot;, & quot; firefox & quot;);
5
caps.SetCapability (& quot; platform & quot;, & quot; Windows 10 & quot;);
6
caps.SetCapability (& quot; version & quot;, & quot; 92 & quot;);
7
caps.SetCapability (& quot; build & quot;, myTestBuild);
8
caps.SetCapability (& quot; name & quot;, myTestName);
9
var driver = new RemoteWebDriver (new Uri (SauceURL), capableness);
10
11
// After:
12
13
var browserOptions = new FirefoxOptions ();
14
browserOptions.PlatformName = & quot; Windows 10 & quot;;
15
browserOptions.BrowserVersion = & quot; 92 & quot;;
16
var sauceOptions = new Dictionary & lt; string, object & gt; ();
17
sauceOptions.Add (& quot; build & quot;, myTestBuild);
18
sauceOptions.Add (& quot; name & quot;, myTestName);
19
browserOptions.AddAdditionalOption (& quot; sauce: options & quot;, sauceOptions);
20
var driver = ​​new RemoteWebDriver (new Uri (SauceURL), options);
21

Ruby

1
// Before:
2
3
caps = Selenium::WebDriver::Remote::Capabilities.firefox
4
caps[:platform]=& # x27; Windows 10 & # x27;
5
caps[:version]=& # x27; 92 & # x27;
6
caps[:build]=my_test_build
7
caps[:name]=my_test_name
8
driver = Selenium::WebDriver.for:remote, url: sauce_url,desired_capabilities: caps
9
10
// After:
11
12
options = Selenium::WebDriver::Options.firefox
13
options.browser_version=& # x27; latest & # x27;
14
options.platform_name=& # x27; Windows 10 & # x27;
15
sauce_options={}
16
sauce_options[:build]=my_test_build
17
sauce_options[:name]=my_test_name
18
options.add_option(& # x27; sauce: choice & # x27;,sauce_options)
19
driver = Selenium::WebDriver.for:remote, url: sauce_url,capabilities: options
20

Python

1
// Before:
2
3
caps ={}
4
caps[& # x27; browserName & # x27;]=& # x27; firefox & # x27;
5
caps[& # x27; platform & # x27;]=& # x27; Windows 10 & # x27;
6
caps[& # x27; variant & # x27;]=& # x27; 92 & # x27;
7
caps[& # x27; build & # x27;]=my_test_build
8
caps[& # x27; name & # x27;]=my_test_name
9
driver = webdriver.Remote(sauce_url,desired_capabilities=caps)
10
11
// After:
12
13
from selenium.webdriver.firefox.options import Options asFirefoxOptions
14
options =FirefoxOptions()
15
options.browser_version=& # x27; 92 & # x27;
16
options.platform_name=& # x27; Windows 10 & # x27;
17
sauce_options={}
18
sauce_options[& # x27; build & # x27;]=my_test_build
19
sauce_options[& # x27; name & # x27;]=my_test_name
20
options.set_capability(& # x27; sauce: options & # x27;,sauce_options)
21
driver = webdriver.Remote(sauce_url, options=options)
22

For more combinations and examples, check theSauce Labs program configurator.

Find element (s) utility methods in Java

The utility methods to discover component in the Java bindings (FindsByinterface) have been removed as they were meant for internal use only. The following code sample excuse this best.

Pro tip: Tools like SUSA can handle this autonomously — upload your app and get results without writing a single test script.

1
// Before:
2
3
driver.findElementByClassName (& quot; className & quot;);
4
driver.findElementByCssSelector (& quot; .className & quot;);
5
driver.findElementById (& quot; elementId & quot;);
6
driver.findElementByLinkText (& quot; linkText & quot;);
7
driver.findElementByName (& quot; elementName & quot;);
8
driver.findElementByPartialLinkText (& quot; partialText & quot;);
9
driver.findElementByTagName (& quot; elementTagName & quot;);
10
driver.findElementByXPath (& quot; xPath & quot;);
11
12
// After:
13
14
driver.findElement (By.className (& quot; className & quot;));
15
driver.findElement (By.cssSelector (& quot; .className & quot;));
16
driver.findElement (By.id (& quot; elementId & quot;));
17
driver.findElement (By.linkText (& quot; linkText & quot;));
18
driver.findElement (By.name (& quot; elementName & quot;));
19
driver.findElement (By.partialLinkText (& quot; partialText & quot;));
20
driver.findElement (By.tagName (& quot; elementTagName & quot;));
21
driver.findElement (By.xpath (& quot; xPath & quot;));
22
23
// All the findElements * hold been removed as well.
24
25
//Before:
26
27
driver.findElementsByClassName (& quot; className & quot;);
28
driver.findElementsByCssSelector (& quot; .className & quot;);
29
driver.findElementsById (& quot; elementId & quot;);
30
driver.findElementsByLinkText (& quot; linkText & quot;);
31
driver.findElementsByName (& quot; elementName & quot;);
32
driver.findElementsByPartialLinkText (& quot; partialText & quot;);
33
driver.findElementsByTagName (& quot; elementTagName & quot;);
34
driver.findElementsByXPath (& quot; xPath & quot;);
35
36
// After:
37
38
driver.findElements (By.className (& quot; className & quot;));
39
driver.findElements (By.cssSelector (& quot; .className & quot;));
40
driver.findElements (By.id (& quot; elementId & quot;));
41
driver.findElements (By.linkText (& quot; linkText & quot;));
42
driver.findElements (By.name (& quot; elementName & quot;));
43
driver.findElements (By.partialLinkText (& quot; partialText & quot;));
44
driver.findElements (By.tagName (& quot; elementTagName & quot;));
45
driver.findElements (By.xpath (& quot; xPath & quot;));
46

Upgrading dependencies

Check the subsections below to install Selenium 4 and have your project dependencies upgraded.

Java

The process of upgrading Selenium look on which build tool is being used. We will continue the most common ones for Java, which areMaven and Gradle. The minimum Java version required is still 8.

Maven

1
// Before:
2
3
<dependencies>
4
<!--more dependencies...-->
5
<dependency>
6
<groupId>org.seleniumhq.selenium</groupId>
7
<artifactId>selenium-java</artifactId>
8
<version>3.141.59</version>
9
</dependency>
10
<!--more habituation...-->
11
</dependencies>
12
13
// After:
14
15
<dependencies>
16
<!--more dependencies...-->
17
<dependency>
18
<groupId>org.seleniumhq.selenium</groupId>
19
<artifactId>selenium-java</artifactId>
20
<version>4.0.0</version>
21
</dependency>
22
<!--more dependencies...-->
23
</dependencies>
24

After create the change, you could executemvn clean compileon the same directory where thepom.xml file is.

Gradle

1
// Before:
2
3
plugins {
4
id & # x27; java & # x27;
5
}
6
7
group & # x27; org.example & # x27;
8
version & # x27; 1.0-SNAPSHOT & # x27;
9
10
deposit{
11
mavenCentral()
12
}
13
14
dependencies{
15
testImplementation& # x27; org.junit.jupiter: junit-jupiter-api:5.7.0 & # x27;
16
testRuntimeOnly& # x27; org.junit.jupiter: junit-jupiter-engine:5.7.0 & # x27;
17
implementation group:& # x27; org.seleniumhq.selenium & # x27;,name:& # x27; selenium-java & # x27;,version:& # x27; 3.141.59 & # x27;
18
}
19
20
test {
21
useJUnitPlatform()
22
23
}
24
25
// After:
26
27
plugins {
28
id & # x27; java & # x27;
29
}
30
31
group & # x27; org.example & # x27;
32
version & # x27; 1.0-SNAPSHOT & # x27;
33
34
repositories{
35
mavenCentral()
36
}
37
38
dependencies{
39
testImplementation& # x27; org.junit.jupiter: junit-jupiter-api:5.7.0 & # x27;
40
testRuntimeOnly& # x27; org.junit.jupiter: junit-jupiter-engine:5.7.0 & # x27;
41
effectuation group:& # x27; org.seleniumhq.selenium & # x27;,name:& # x27; selenium-java & # x27;,version:& # x27; 4.0.0 & # x27;
42
}
43
44
test {
45
useJUnitPlatform()
46
}
47

After making the change, you could fulfill ./gradlew clean build
on the same directory where the build.gradle file is.

To check all the Java releases, you can lead toMVNRepository.

C#

The place to get update for Selenium 4 in C # isNuGet. Under theSelenium.WebDriver packetyou can get the instructions to update to the latest version. Inside of Visual Studio, through the NuGet Package Manager you can execute:

PM & gt; Install-Package Selenium.WebDriver -Version 4.0.0

Python

The most crucial change to use Python is the minimum required variant. Selenium 4 will require a minimum Python 3.7 or high. More details can be found at thePython Package Index. To upgrade from the command line, you can execute:

pip install selenium==4.0.0

Ruby

The update details for Selenium 4 can be seen at theselenium-webdrivergem in RubyGems. To install the modish version, you can execute:

gem install selenium-webdriver

To add it to your Gemfile:

gem & # x27; selenium-webdriver & # x27;, & # x27; ~ & gt; 4.0.0 & # x27;

JavaScript

The selenium-webdriver package can be found at the Node package manager,npmjs. Selenium 4 can be foundhere. To install it, you could either execute:
npm install selenium-webdriver

Or, update your package. json and run npm install:

{
& quot; name & quot;: & quot; selenium-tests & quot;,
& quot; version & quot;: & quot; 1.0.0 & quot;,
& quot; dependencies & quot;: {
& quot; selenium-webdriver & quot;: & quot; ^4.0.0 & quot;
}
}

Possible Errors and Deprecation Messages

Here is a set of codification examples that will help to overcome the deprecation messages you might encounter after upgrading to Selenium 4.

Java

Waits and Timeout

The parameters obtain in Timeout have switched from expecting (long time, TimeUnit unit) to expect (Duration length).

1
// Before:
2
3
driver.manage () .timeouts () .implicitlyWait (10, TimeUnit.SECONDS);
4
driver.manage () .timeouts () .setScriptTimeout (2, TimeUnit.MINUTES);
5
driver.manage () .timeouts () .pageLoadTimeout (10, TimeUnit.SECONDS);
6
7
// After:
8
9
driver.manage () .timeouts () .implicitlyWait (Duration.ofSeconds (10));
10
driver.manage () .timeouts () .scriptTimeout (Duration.ofMinutes (2));
11
driver.manage () .timeouts () .pageLoadTimeout (Duration.ofSeconds (10));
12

Waits are also expecting different parameters now. WebDriverWait is now expecting a Duration instead of a long for timeout in seconds and millisecond. The withTimeout and pollingEvery utility methods from FluentWait have shift from expecting (long time, TimeUnit unit) to expect (Duration duration).

1
// Before:
2
3
new WebDriverWait (driver, 3)
4
.until (ExpectedConditions.elementToBeClickable (By.cssSelector (& quot; # id & quot;)));
5
6
Wait & lt; WebDriver & gt; wait = new FluentWait & lt; WebDriver & gt; (driver)
7
.withTimeout (30, TimeUnit.SECONDS)
8
.pollingEvery (5, TimeUnit.SECONDS)
9
.ignoring (NoSuchElementException.class);
10
11
// After:
12
13
new WebDriverWait (driver, Duration.ofSeconds (3))
14
.until (ExpectedConditions.elementToBeClickable (By.cssSelector (& quot; # id & quot;)));
15
16
Wait & lt; WebDriver & gt; wait = new FluentWait & lt; WebDriver & gt; (driver)
17
.withTimeout (Duration.ofSeconds (30))
18
.pollingEvery (Duration.ofSeconds (5))
19
.ignoring (NoSuchElementException.class);
20

Merging Capabilities is No Longer Changing the Calling Object

It was possible to merge a different set of capabilities into another set, and it was mutating the ring object. Now, the result of the merge operation want to be assigned.

1
// Before:
2
3
MutableCapabilities potentiality = new MutableCapabilities ();
4
capabilities.setCapability (& quot; platformVersion & quot;, & quot; Windows 10 & quot;);
5
FirefoxOptions options = new FirefoxOptions ();
6
options.setHeadless (true);
7
options.merge (capableness);
8
9
// As a result, the options object was become modify.
10
// After:
11
12
MutableCapabilities capabilities = new MutableCapabilities ();
13
capabilities.setCapability (& quot; platformVersion & quot;, & quot; Windows 10 & quot;);
14
FirefoxOptions pick = new FirefoxOptions ();
15
options.setHeadless (true);
16
options = options.merge (capacity);
17

The resolution of themergecall needs to be allot to an objective.

Firefox Legacy

Before GeckoDriver was around, the Selenium labor had a driver implementation to automate Firefox (adaptation & lt; 48). However, this execution is not need anymore as it does not act in recent edition of Firefox. To avoid major issues when upgrading to Selenium 4, thesetLegacyselection will be shown as depreciate. The recommendation is to quit using the old implementation and rely only on GeckoDriver. The following code will show thesetLegacyline deprecated after upgrading.

FirefoxOptions options = new FirefoxOptions ();
options.setLegacy (true);

BrowserType

The BrowserType interface has be around for a long time, withal it is getting deprecated in favor of the new Browser interface.

1
// Before:
2
3
MutableCapabilitiescapability=newMutableCapabilities();
4
potentiality.setCapability(& quot; browserVersion & quot;,& quot; 92 & quot;);
5
capabilities.setCapability(& quot; browserName & quot;,BrowserType.FIREFOX);
6
7
// After:
8
9
MutableCapabilitiescapacity=newMutableCapabilities();
10
capabilities.setCapability(& quot; browserVersion & quot;,& quot; 92 & quot;);
11
capabilities.setCapability(& quot; browserName & quot;,Browser.FIREFOX);
12

C#

AddAdditionalCapability is depreciate. Instead, AddAdditionalOption is recommended. Here is an example showing this:

1
// Before:
2
3
var browserOptions = new ChromeOptions ();
4
browserOptions.PlatformName = & quot; Windows 10 & quot;;
5
browserOptions.BrowserVersion = & quot; up-to-the-minute & quot;;
6
var sauceOptions = new Dictionary & lt; string, object & gt; ();
7
browserOptions.AddAdditionalCapability (& quot; sauce: options & quot;, sauceOptions, true);
8
9
// After:
10
11
var browserOptions = new ChromeOptions ();
12
browserOptions.PlatformName = & quot; Windows 10 & quot;;
13
browserOptions.BrowserVersion = & quot; modish & quot;;
14
var sauceOptions = new Dictionary & lt; string, object & gt; ();
15
browserOptions.AddAdditionalOption (& quot; sauce: options & quot;, sauceOptions);
16

Summary

We move through the major changes to be taken into consideration when upgrading to Selenium 4. Covering the different aspects to cover when test code is prepared for the upgrade, including suggestions on how to prevent potential issues that can show up when using the new edition of Selenium. To finalize, we also covered a set of possible issues that you can bump into after upgrading, and we share potential fixture for those issues.

Titus Fortner

Sr. Developer Experience Engineer, Sauce Labs

Diego Molina

Staff Software Engineer at Sauce Labs

Published:
Oct 12, 2021
Share this post
Copy Share Link
LinkedIn
© 2026 Sauce Labs Inc., all rights reserved. SAUCE and SAUCE LABS are registered trademarks owned by Sauce Labs Inc. in the United States, EU, and may be registered in other jurisdictions.
robot
quote

Automate This With SUSA

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts needed.

Try SUSA Free

Test Your App Autonomously

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.

Try SUSA Free