Automatic download of appropriate chromedriver for Selenium in Python
Asked Answered
C

9

20

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!

Cloots answered 26/5, 2020 at 7:47 Comment(0)
A
28

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)
Animation answered 26/5, 2020 at 13:23 Comment(3)
Thanks, how to be sure it suits the chrome browser version ? If lastest driver is 88 and my browser is 87...Bib
from win32com.client import Dispatch def get_version_via_com(filename): parser = Dispatch("Scripting.FileSystemObject") version = parser.GetFileVersion(filename) return version if __name__ == "__main__": path = r"C:\Program Files\Google\Chrome\Application\chrome.exe" print get_version_via_com(path) you can get the version number and store it as part of version_number = response.text line.Animation
The archive is either in unknown format or damaged. Somehow downloading archive is no longer working with wget, as it download a small part of it....Premonish
N
15

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

Numb answered 27/8, 2021 at 15:53 Comment(1)
Very nice, it just works!Timpani
B
14

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/

Boehike answered 15/1, 2021 at 11:16 Comment(0)
K
8

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

Kauppi answered 26/5, 2020 at 7:50 Comment(1)
Thanks, was new to me, unfortunately no Py2.7 support (I know, outdated, but sometimes old projects can't migrate...) :)Cloots
A
7

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_USER\Software\Google\Chrome\BLBeacon" /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) 
 
Androw answered 26/4, 2021 at 12:54 Comment(1)
liked this solution, can make it slightly shorter by replacing reply.rstrip() and reply.lstrip() with reply.strip(). Instead of using file with the target_name, I saved the file as chromdriver.exe and created a versionlog where I can check the version. Thanks.Anomalism
S
4

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()
Sennight answered 3/2, 2023 at 6:59 Comment(3)
Simple and concise answer!Anastrophe
What's with the time.sleep(sys.maxsize) at the end of it? What's the goal?Repentant
@Repentant That is to keep the Chrome window open.Sennight
W
3

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)
Wellknit answered 2/10, 2021 at 10:33 Comment(1)
It should be noted as of 4-18-2024, visiting the URL "chromedriver.storage.googleapis.com/LATEST_RELEASE" returns version 114 as the latest release, which is incorrect as the current release is 124. Looks like the appropriate URL is this one. googlechromelabs.github.io/chrome-for-testing/…Cirrocumulus
C
1

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_USER\Software\Google\Chrome\BLBeacon" /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)

Cane answered 29/9, 2022 at 2:0 Comment(0)
S
1

I used supputuri's approach for versions > 115:

import requests
import wget
import zipfile
import os

# get the latest chrome driver version number
url = 'https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_STABLE'
response = requests.get(url)
version_number = response.text

print(version_number)

# build the donwload url
download_url = "https://storage.googleapis.com/chrome-for-testing-public/" + version_number +"/win64/chromedriver-win64.zip"
print(download_url)

# 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)
Startle answered 7/6, 2024 at 17:5 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.