How to automatically update chromedriver for Selenium when Chrome updates

How to automatically update chromedriver for Selenium when Chrome updates

I'm really tired of opening up a script to run some monthly reports, only to find that Chrome has updated again, which means my chromedriver breaks my script. Let's automate this!

💡
This article and script has been updated on May 22, 2024 to fix the breaking changes introduced in Chrome v. 116+.

Normally to fix this error:

selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 97
Current browser version is 99.xxx

I have to find out which version of chromedriver I need, download the file, unzip, and clean up my workspace.

Time for some automation. (If you're comfortable with shell scripts or just want to cut to the chase, get the full script at the bottom—and the video version is down there, too)

Where to Save the Script and the chromedriver File

I am keeping it simple by saving this shell script in the same path as my current chromedriver. That way we simply download the chromedriver into the same directory and we know that the script will be there, bundled together.

Create a new .sh file in the folder that you want to put your chromedriver. I'm calling my file get-latest-chromedriver.sh

Shell Script to Download the Correct File

First thing to do in this script is get the version of Chrome that I have on my computer. The manual way takes way too long, though...

Getting the current version of Chrome using the Terminal

Assuming that you are on a Mac and have simply installed Chrome into your Applications folder, you can actually get your Chrome version by throwing this into your terminal:

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version

Note that those escaped spaces are important (\ ) The output should be something like this:

Google Chrome 125.0.6422.76

That's almost perfect, but we just need the numbers, so we're going to cut out some of that output in order to create a CHROME_VERSION variable that we can use later.

Cutting the Output in the Terminal

If we want to get rid of parts of the output, we can use the "cut" utility in the Terminal. We take our original command and add the pipe | and the cut, like this:

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version | cut -d ' ' -f3

The -d flag is to identify the "delimiter" or the character on which we want to make our "cuts." Right now, I want to get rid of the text from the output (Google Chrome ...) and just leave the numbers, so I chose a single space ' ' for the delimiter.

The -f flag is used to identify the "fields" or segments that we want to capture. In this case, I only want field 3, because that's the segment containing the numbers. Think of it like this:

Cutting our output string by each space, we end up with three groups

Finally, we really only need the first three sets of numbers in our Chrome version, so we'll cut off the set of digits after the last period (99.0.4844 instead of 99.0.4844.51).

To do this, we can just chain on another cut, making our command look like this:

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version | cut -d ' ' -f3 | cut -d '.' -f1-3

In this case our delimiter (-d flag) is the period '.' and our fields (-f flag) is the first three segments, inclusive.

We can cut this string on the periods, since we want to get rid of the last set of numbers (set #4)

Using the Chrome Version to Get the Corresponding Latest Release Version

The last thing to do is to put our formatted Chrome version number into a URL and grab the number that it presents. We're basically using an API to check what chromedriver version we need for our current Chrome version.

To consolidate all of this, I decided to add an xargs command on the end of our previous command. This way we can easily port our chrome version into "curl" and finally assign it to our variable CHROME_VERSION.

First, to break down the xargs and curl call:

... | xargs -I {} curl https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_{}

We're piping in our cut-up Chrome version (99.0.4844, for example) and xargs is making it available to use in the curl call. It assigns that version number to the curly braces {} and then when the program sees those brackets at the end of the URL, it swaps the brackets with the Chrome version. Those brackets are just placeholders so we know where we want the number to get inserted.

If the URL were written out by a human, it would look like this:

https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_99.0.4844

The curl command then sends a request to the URL and gets the following back as a response:

99.0.4844.51

Since we want to keep this number (it may be different than the version number we started with—in this case it wasn't), we'll assign it to a variable:

CHROME_VERSION=$(/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version | cut -d ' ' -f3 | cut -d '.' -f1-3 | xargs -I {} curl https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_{})

Note that we named the variable CHROME_VERSION= and then put a $(...) wrapped around our entire command.

Downloading the zip file with curl

If you download the chromedriver the manual way, you'll need to choose a platform type (your OS and hardware).

As of this update, there are 5 platform types:

  • linux64
  • mac-arm64
  • mac-x64
  • win32
  • win64

The zip file name is constructed using this pattern:
chromedriver-<platformtype>.zip

Since I'm on a Mac in this case, I choose the zip file named chromedriver-mac-x64.zip

We'll now store all of this in a few variables in our script so we can use it multiple times, but easily update the script as needed:

# ...(chrome version command from above)...

PLATFORM_NAME=mac-x64
FILE_NAME=chromedriver-mac-x64
ZIP_FILE_NAME=$FILE_NAME.zip

Now we can insert the zip file name and the chrome version into our final curl call that will download the correct file for us.

# ...

curl -o ./$ZIP_FILE_NAME "https://storage.googleapis.com/chrome-for-testing-public/$CHROME_VERSION/$PLATFORM_NAME/$ZIP_FILE_NAME"

The -o flag in curl allows us to download the file at the provided URL. After the -o, we define the path to the file and the name of the file. This is why we made the zip file name a variable just before this.

-o ./$ZIP_FILE_NAME means that we're going to save our file in our current directory, using the name stored in the ZIP_FILE_NAME variable.

Unzip the downloaded file automatically in the shell script

It's actually pretty easy to unzip a file in the Terminal. If you're on a Mac, you should already have an "unzip" Terminal utility. If you don't have it, you should be able to run sudo apt-get install unzip, to get install it. You may want to check out this forum post from the Stack Exchange: https://askubuntu.com/questions/86849/how-to-unzip-a-zip-file-from-the-terminal

We'll go ahead and put the unzip command into our script now:

...

unzip -o $ZIP_FILE_NAME

I've added the -o flag to automatically overwrite any pre-existing chromedriver file I have in my current directory. This is optional, but that means you'll get a prompt when you run this shell script asking you how to handle the new file (whether to overwrite, rename, etc.).

As of Chrome 116+, they've been zipping up the chromedriver in a folder, so the -o flag is technically unused, but I'm keeping it just in case. I don't ever need to keep older versions of chromedriver, so overwriting is my preference. Feel free to remove -o if you need.

Clean up your directory and remove the Apple quarantine

Now that the chromedriver is downloaded and unzipped, I don't want to keep the zip file. Let's clean up the directory by adding this line to the script:

...

rm $ZIP_FILE_NAME

This will delete the zip file we downloaded (not the unzipped chromedriver file, of course).

⚠️
As always, use remove commands in bash script with extreme caution. I'm not responsible for any loss of data you experience. If you are concerned, simply delete this line. I've commented this line out in the full script below—uncomment at your own risk.

Finally, you may encounter this alert box about Apple quarantine when trying to use chromedriver in your other scripts:

In order to automatically remove this, you can add this to your shell script:

xattr -d com.apple.quarantine chromedriver

It seemed like some versions of the chromedriver didn't actually need this xattr command in order to run immediately after being downloaded / unzipped. In fact, On the version I've used in this example, I kept the xattr command in my script and got this error after running the shell script:

xattr: chromedriver: No such xattr: com.apple.quarantine

Despite the error, I was still able to run my Selenium webdriver using the new chromedriver without any problem and no quarantine alert.

You can always comment that line out and bring it back if you find you need to always un-quarantine the files.

Final Result

This was a bit of work and uses some advanced command line techniques, but this should help us stay on top of the frequent Chrome updates that always break our Selenium code ;)

Here's the full code with comments to help us remember everything:

#!/bin/sh
# Downloads chromedriver based on your current chrome version, unzips, deletes zip file


# Get current chrome version
# separate version from other output (cut...-f3)
# separate first 3 fields (segments) of the version number (cut...-f1-3)
# Pass version number into xargs/curl call
CHROME_VERSION=$(/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version | cut -d ' ' -f3 | cut -d '.' -f1-3 | xargs -I {} curl https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_{})


PLATFORM_NAME=mac-x64
FILE_NAME=chromedriver-mac-x64
ZIP_FILE_NAME=$FILE_NAME.zip

# Insert CHROME_VERSION, PLATFORM_NAME, and ZIP_FILE_NAME into download URL:
curl -o ./$ZIP_FILE_NAME "https://storage.googleapis.com/chrome-for-testing-public/$CHROME_VERSION/$PLATFORM_NAME/$ZIP_FILE_NAME"

# https://askubuntu.com/questions/86849/how-to-unzip-a-zip-file-from-the-terminal
# If the unzip command isn't already installed on your system, then run:
# sudo apt-get install unzip

# Unzip. -o flag means overwrite
unzip -o $ZIP_FILE_NAME

# Go into the unzipped file
cd $FILE_NAME

# Clean / remove quarantine for Apple in order to open it
xattr -d com.apple.quarantine chromedriver

# Move file out of the zipped folder to one above
mv chromedriver ../

# Go back out and delete the ZIP file
cd ../

# Uncomment at your own risk (deletes the zip file)
# rm $ZIP_FILE_NAME

To run this script, open your terminal and go into the directory that you saved this shell script.

If this is a brand new script, you may need to make it executable, so run this command first:
chmod +x SCRIPTNAME.sh

Then use ./SCRIPTNAME.sh to run (in my case, using my file name, I would run it like this: ./get-latest-chromedriver.sh)


Watch me go through the whole script (original video, not yet updated for Chrome 116+):