Automatic download of appropriate chromedriver for Selenium in Python

Question:

Unfortunately, Chromedriver always is version-specific to the Chrome version you have installed.
So when you pack your python code AND a chromedriver via PyInstaller in a deployable .exe-file for Windows, it will not work in most cases as you won’t be able to have all chromedriver versions in the .exe-file.

Anyone knows a way on how to download the correct chromedriver from the website automatically?

If not, I’ll come up with a code to download the zip-file and unpack it to temp.

Thanks!

Asked By: tim

||

Answers:

Webdriver Manager will do that for you. refer this link https://pypi.org/project/webdriver-manager/

Answered By: NarendraR

Here is the other solution, where webdriver_manager does not support. This script will get the latest chrome driver version downloaded.

import requests
import wget
import zipfile
import os

# get the latest chrome driver version number
url = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE'
response = requests.get(url)
version_number = response.text

# build the donwload url
download_url = "https://chromedriver.storage.googleapis.com/" + version_number +"/chromedriver_win32.zip"

# download the zip file using the url built above
latest_driver_zip = wget.download(download_url,'chromedriver.zip')

# extract the zip file
with zipfile.ZipFile(latest_driver_zip, 'r') as zip_ref:
    zip_ref.extractall() # you can specify the destination folder path here
# delete the zip file downloaded above
os.remove(latest_driver_zip)
Answered By: supputuri

Here is one more way
For Python –

import chromedriver_autoinstaller
from selenium import webdriver

opt = webdriver.ChromeOptions()
opt.add_argument("--start-maximized")

chromedriver_autoinstaller.install()
driver = webdriver.Chrome(options=opt)
driver.get('https://stackoverflow.com/')

here is more info

https://pypi.org/project/chromedriver-autoinstaller/

Answered By: Hietsh Kumar

I have a slightly fancier version

It will detected what chrome version you have, grab the correct driver

def download_chromedriver():
    def get_latestversion(version):
        url = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE_' + str(version)
        response = requests.get(url)
        version_number = response.text
        return version_number
    def download(download_url, driver_binaryname, target_name):
        # download the zip file using the url built above
        latest_driver_zip = wget.download(download_url, out='./temp/chromedriver.zip')

        # extract the zip file
        with zipfile.ZipFile(latest_driver_zip, 'r') as zip_ref:
            zip_ref.extractall(path = './temp/') # you can specify the destination folder path here
        # delete the zip file downloaded above
        os.remove(latest_driver_zip)
        os.rename(driver_binaryname, target_name)
        os.chmod(target_name, 755)
    if os.name == 'nt':
        replies = os.popen(r'reg query "HKEY_CURRENT_USERSoftwareGoogleChromeBLBeacon" /v version').read()
        replies = replies.split('n')
        for reply in replies:
            if 'version' in reply:
                reply = reply.rstrip()
                reply = reply.lstrip()
                tokens = re.split(r"s+", reply)
                fullversion = tokens[len(tokens) - 1]
                tokens = fullversion.split('.')
                version = tokens[0]
                break
        target_name = './bin/chromedriver-win-' + version + '.exe'
        found = os.path.exists(target_name)
        if not found:
            version_number = get_latestversion(version)
            # build the donwload url
            download_url = "https://chromedriver.storage.googleapis.com/" + version_number +"/chromedriver_win32.zip"
            download(download_url, './temp/chromedriver.exe', target_name)

    elif os.name == 'posix':
        reply = os.popen(r'chromium --version').read()

        if reply != '':
            reply = reply.rstrip()
            reply = reply.lstrip()
            tokens = re.split(r"s+", reply)
            fullversion = tokens[1]
            tokens = fullversion.split('.')
            version = tokens[0]
        else:
            reply = os.popen(r'google-chrome --version').read()
            reply = reply.rstrip()
            reply = reply.lstrip()
            tokens = re.split(r"s+", reply)
            fullversion = tokens[2]
            tokens = fullversion.split('.')
            version = tokens[0]

        target_name = './bin/chromedriver-linux-' + version
        print('new chrome driver at ' + target_name)
        found = os.path.exists(target_name)
        if not found:
            version_number = get_latestversion(version)
            download_url = "https://chromedriver.storage.googleapis.com/" + version_number +"/chromedriver_linux64.zip"
            download(download_url, './temp/chromedriver', target_name) 
 
Answered By: Hairy Ass

As of Aug-2021, this is the status :-

chromedriver-autoinstaller

Automatically download and install chromedriver that supports the
currently installed version of chrome. This installer supports Linux,
MacOS and Windows operating systems.

Installation

pip install chromedriver-autoinstaller

Usage

Just type import chromedriver_autoinstaller in the module you want to use chromedriver.

Example


from selenium import webdriver
import chromedriver_autoinstaller


chromedriver_autoinstaller.install()  # Check if the current version of chromedriver exists
                                      # and if it doesn't exist, download it automatically,
                                      # then add chromedriver to path

driver = webdriver.Chrome()
driver.get("http://www.python.org")
assert "Python" in driver.title

Reference link here

Answered By: cruisepandey

You could use this solution. It will do two things:

  1. Check locally in your computer for the driver version and compare it with the latest version available online.
  2. The latest online version will be downloaded if it does not match your local version.
from selenium import webdriver
import requests
import zipfile
import wget
import subprocess
import os


CHROMEDRIVER_PATH =  # Insert your Chromedriver path here
CHROMEDRIVER_FOLDER = os.path.dirname(CHROMEDRIVER_PATH)
LATEST_DRIVER_URL = "https://chromedriver.storage.googleapis.com/LATEST_RELEASE"


def download_latest_version(version_number):
    print("Attempting to download latest driver online......")
    download_url = "https://chromedriver.storage.googleapis.com/" + version_number + "/chromedriver_win32.zip"
    # download zip file
    latest_driver_zip = wget.download(download_url, out=CHROMEDRIVER_FOLDER)
    # read & extract the zip file
    with zipfile.ZipFile(latest_driver_zip, 'r') as downloaded_zip:
        # You can chose the folder path to extract to below:
        downloaded_zip.extractall(path=CHROMEDRIVER_FOLDER)
    # delete the zip file downloaded above
    os.remove(latest_driver_zip)


def check_driver():
    # run cmd line to check for existing web-driver version locally
    cmd_run = subprocess.run("chromedriver --version",
                             capture_output=True,
                             text=True)
    # Extract driver version as string from terminal output
    local_driver_version = cmd_run.stdout.split()[1]
    print(f"Local driver version: {local_driver_version}")
    # check for latest chromedriver version online
    response = requests.get(LATEST_DRIVER_URL)
    online_driver_version = response.text
    print(f"Latest online chromedriver version: {online_driver_version}")
    if local_driver_version == online_driver_version:
        return True
    else:
        download_latest_version(online_driver_version)
Answered By: Competency Test

This solution uses default python libraries and will download the closest matching version from internet depending on your current locally installed version of Chrome. My linux laptop has Google Chrome version 97.0.4692.99 loaded, however the closest version from the drivers link was 97.0.4692.71. If needed also, you can change the value of the parameter latest in chrome_driver_url to force download the latest chrome version.

import os
import ssl, shutil, re, platform
import zipfile
from urllib.request import urlopen
from pathlib import Path

import difflib


def chrome_driver_url(latest=False):
    def current_chrome_version():
        CHROME_RELEASE_URL = "https://sites.google.com/chromium.org/driver/downloads?authuser=0"
        try:
            response = urlopen(CHROME_RELEASE_URL,context=ssl.SSLContext(ssl.PROTOCOL_TLS)).read()
        except ssl.SSLError:
            response = urlopen(CHROME_RELEASE_URL,).read()

        downloading_version = re.findall(b"ChromeDriver d{2,3}.0.d{4}.d+", response)
        downloading_version = [x.decode().split(" ")[1] for x in downloading_version]
        downloading_version.sort(key=lambda x: [int(i) if i.isdigit() else i for i in x.split('.')])
        downloading_version.reverse()
        osname = platform.system()
        if osname == 'Darwin':
            installpath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
            verstr = os.popen(f"{installpath} --version").read().strip('Google Chrome ').strip()
            ver_to_download = difflib.get_close_matches(verstr, downloading_version)
            ver_to_download = ver_to_download[0]
            return ver_to_download
        elif osname == 'Windows':
            verstr = os.popen('reg query "HKEY_CURRENT_USERSoftwareGoogleChromeBLBeacon" /v version').read().strip().split(" ")
            verstr = verstr[-1]
            ver_to_download = difflib.get_close_matches(verstr, downloading_version)
            ver_to_download = ver_to_download[0]
            return ver_to_download
        elif osname == 'Linux':
            installpath = "/usr/bin/google-chrome"
            verstr = os.popen(f"{installpath} --version").read().strip('Google Chrome ').strip()
            ver_to_download = difflib.get_close_matches(verstr, downloading_version)
            ver_to_download = ver_to_download[0]
            return ver_to_download
        else:
            raise NotImplemented(f"Unknown OS '{osname}'")

    if latest:
        CHROME_RELEASE_URL = "https://sites.google.com/chromium.org/driver/downloads?authuser=0"
        try:
            response = urlopen(CHROME_RELEASE_URL, context=ssl.SSLContext(ssl.PROTOCOL_TLS)).read()
        except ssl.SSLError:
            response = urlopen(CHROME_RELEASE_URL).read()

        downloading_version = re.findall(b"ChromeDriver d{2,3}.0.d{4}.d+", response)[0].decode().split()[1]
    else:
        downloading_version = current_chrome_version()

    system = platform.system()
    if system == "Windows":
        url = f"https://chromedriver.storage.googleapis.com/{downloading_version}/chromedriver_win32.zip"
    elif system == "Darwin":
        # M1
        if platform.processor() == 'arm':
            url = f"https://chromedriver.storage.googleapis.com/{downloading_version}/chromedriver_mac64_m1.zip"
        else:
            url = f"https://chromedriver.storage.googleapis.com/{downloading_version}/chromedriver_mac64.zip"
    elif system == "Linux":
        url = f"https://chromedriver.storage.googleapis.com/{downloading_version}/chromedriver_linux64.zip"
    return url


def download_chrome_driver(drivers_dir):
    driver_name = "chromedriver.exe" if platform.system() == "Windows" else "chromedriver"
    if (drivers_dir / driver_name).exists():
            return
    url = chrome_driver_url()
    try:
        response = urlopen(url, context=ssl.SSLContext(ssl.PROTOCOL_TLS))  
    except ssl.SSLError:
        response = urlopen(url)  

    zip_file_path = drivers_dir / Path(url).name
    with open(zip_file_path, 'wb') as zip_file:
        while True:
            chunk = response.read(1024)
            if not chunk:
                break
            zip_file.write(chunk)

    extracted_dir = drivers_dir / zip_file_path.stem
    with zipfile.ZipFile(zip_file_path, "r") as zip_file:
        zip_file.extractall(extracted_dir)
    os.remove(zip_file_path)

    driver_path = drivers_dir / driver_name
    try:
        (extracted_dir / driver_name).rename(driver_path)

    except FileExistsError:
        (extracted_dir / driver_name).replace(driver_path)

    shutil.rmtree(extracted_dir)
    os.chmod(driver_path, 0o755)

if __name__ == "__main__":
    chrome_driver_location = Path("chrome_driver")
    chrome_driver_location.mkdir(exist_ok=True)
    download_chrome_driver(chrome_driver_location)

Answered By: kyrlon

You can use this

import sys
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import ChromiumOptions
from webdriver_manager.chrome import ChromeDriverManager

chrome_options = ChromiumOptions()

service = Service(ChromeDriverManager().install())

driver = webdriver.Chrome(chrome_options=chrome_options, service=service)
driver.get("http://www.python.org")

time.sleep(sys.maxsize)
driver.quit()
Answered By: bikram