Skip to content

Instantly share code, notes, and snippets.

@primaryobjects
Last active October 22, 2022 17:56
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save primaryobjects/70b4864815cf25a40525972d598563f6 to your computer and use it in GitHub Desktop.
Save primaryobjects/70b4864815cf25a40525972d598563f6 to your computer and use it in GitHub Desktop.
Automatically download the latest chromedriver for Selenium in Python. Works on Linux, Mac, Windows. Cross platform!

Automatically Download Chromedriver for Selenium

Automatically detects and downloads the latest chromedriver for Selenium in Python.

Works cross-platform on Linux, Mac, Windows! Include it in your Python code to always ensure the latest chromedriver is available.

Usage

from chromedriver import get_driver

d = get_driver()
d.get('https://www.google.com')

What does it do?

The code performs the following steps listed below.

  1. Open Selenium using Chrome in headless mode.
  2. If step 1 fails, automatically find the latest driver version for Linux, Mac, or Windows.
  3. Download.
  4. Unzip.
  5. Set executable permissions.
  6. Reload Selenium.

Note, loading Selenium requires having chromedriver in the same directory as the Python script. If it fails to load, this is usually due to either the file msising or the version of Chrome on the computer being a higher version than the driver.

#!/usr/bin/env python3
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import WebDriverException, SessionNotCreatedException
import sys
import os
import pathlib
import urllib.request
import re
import zipfile
import stat
from sys import platform
def get_driver():
# Attempt to open the Selenium chromedriver. If it fails, download the latest chromedriver.
driver = None
retry = True
major_version = None
# Determine the version of Chrome installed.
version = get_chrome_version()
if version:
parts = version.split('.')
major_version = parts[0] if len(parts) > 0 else 0
while retry:
retry = False
is_download = False
try:
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options, executable_path='./chromedriver')
except SessionNotCreatedException as e:
if 'This version of ChromeDriver' in e.msg:
is_download = True
print('Warning: You may need to update the Chrome web browser to the latest version. Run Chrome, click Help->About.')
except WebDriverException as e:
if "wrong permissions" in e.msg:
st = os.stat('./chromedriver')
os.chmod('./chromedriver', st.st_mode | stat.S_IEXEC)
retry = True
elif "chromedriver' executable needs to be in PATH" in e.msg:
is_download = True
retry = is_download and download_driver(major_version)
return driver
def download_driver(version=None):
# Find the latest chromedriver, download, unzip, set permissions to executable.
result = False
url = 'https://chromedriver.chromium.org/downloads'
base_driver_url = 'https://chromedriver.storage.googleapis.com/'
file_name = 'chromedriver_' + get_platform_filename()
driver_file_name = 'chromedriver' + '.exe' if platform == "win32" else ''
pattern = 'https://.*?path=(' + (version or '\d+') + '\.\d+\.\d+\.\d+)'
# Download latest chromedriver.
print('Finding latest chromedriver..')
opener = urllib.request.FancyURLopener({})
stream = opener.open(url)
content = stream.read().decode('utf8')
# Parse the latest version.
match = re.search(pattern, content)
if match and match.groups():
# Url of download html page.
url = match.group(0)
# Version of latest driver.
version = match.group(1)
driver_url = base_driver_url + version + '/' + file_name
# Download the file.
print('Version ' + version)
print('Downloading ' + driver_url)
app_path = os.path.dirname(os.path.realpath(__file__))
chromedriver_path = app_path + '/' + driver_file_name
file_path = app_path + '/' + file_name
urllib.request.urlretrieve(driver_url, file_path)
# Unzip the file.
print('Unzipping ' + file_path)
with zipfile.ZipFile(file_path, 'r') as zip_ref:
zip_ref.extractall(app_path)
print('Setting executable permission on ' + chromedriver_path)
st = os.stat(chromedriver_path)
os.chmod(chromedriver_path, st.st_mode | stat.S_IEXEC)
# Cleanup.
os.remove(file_path)
result = True
return result
def get_platform_filename():
filename = ''
is_64bits = sys.maxsize > 2**32
if platform == "linux" or platform == "linux2":
# linux
filename += 'linux'
filename += '64' if is_64bits else '32'
elif platform == "darwin":
# OS X
filename += 'mac64'
elif platform == "win32":
# Windows...
filename += 'win32'
filename += '.zip'
return filename
def extract_version(output):
try:
google_version = ''
for letter in output[output.rindex('DisplayVersion REG_SZ') + 24:]:
if letter != '\n':
google_version += letter
else:
break
return(google_version.strip())
except TypeError:
return
def get_chrome_version():
version = None
install_path = None
try:
if platform == "linux" or platform == "linux2":
# linux
install_path = "/usr/bin/google-chrome"
elif platform == "darwin":
# OS X
install_path = "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
elif platform == "win32":
# Windows...
stream = os.popen('reg query "HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Google Chrome"')
output = stream.read()
version = extract_version(output)
except Exception as ex:
print(ex)
version = os.popen(f"{install_path} --version").read().strip('Google Chrome ').strip() if install_path else version
return version
@kunalworldwide
Copy link

Nice work...but This code has an issue, the loop is infinite, even after downloading the driver. it continues to do so for infinite times.

@primaryobjects
Copy link
Author

I think that can occur when the version of Chrome on your computer is an older version than the latest available driver. In this case, the download completes, but fails to load the driver.

You could modify the code at line 63 to check your version of Chrome installed and download that specific version of the driver instead of the latest.

Feel free to post an update if you add this!

@kunalworldwide
Copy link

kunalworldwide commented Apr 28, 2021

Hi,
Thanks for your response, I have added the method to get the installed version but I am still unable to run chromedriver using executable_path='./chromedriver' parameter, can you help me out?
tried running simple 2-3 lines snippet with the executable_path='./chromedriver' parameter it fails to detect the chromedriver even if it is there

#!/usr/bin/env python3
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import WebDriverException, SessionNotCreatedException
import sys
import os
import pathlib
import urllib.request
import re
import zipfile
import stat
from sys import platform
import platform as pt
cwd = os.getcwd()
def get_driver():
    # Attempt to open the Selenium chromedriver. If it fails, download the latest chromedriver.
    driver = None
    retry = True

    while retry:
        retry = False
        is_download = False

        try:
            options = webdriver.ChromeOptions()
            options.add_argument('--headless')
            driver = webdriver.Chrome(chrome_options=options, executable_path='/home/jackreaper/Documents/Facebook-Birthday-Bot/Stable/chromedriver')
        except SessionNotCreatedException as e:
            if 'This version of ChromeDriver' in e.msg:
                is_download = True
        except WebDriverException as e:
            if "wrong permissions" in e.msg:
                st = os.stat('/home/jackreaper/Documents/Facebook-Birthday-Bot/Stable/chromedriver')
                os.chmod('/home/jackreaper/Documents/Facebook-Birthday-Bot/Stable/chromedriver', st.st_mode | stat.S_IEXEC)
                retry = True
            elif "chromedriver' executable needs to be in PATH" in e.msg:
                is_download = True

        retry = is_download and download_driver()

    return driver

def get_chrome_version():
    os_name = pt.system()
    if os_name == 'Darwin':
        installation_path = "/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
    elif os_name == 'Windows':
        installation_path = "C:\Program Files\Google\Chrome\Application\chrome.exe"
    elif os_name == 'Linux':
        installation_path = "/usr/bin/google-chrome"
    else:
        raise NotImplemented(f"Unknown OS '{os_name}'")

    version_str = os.popen(f"{installation_path} --version").read().strip('Google Chrome ').strip()
    return version_str
    
def download_driver():
    # Find the latest chromedriver, download, unzip, set permissions to executable.
    result = False
    url = 'https://chromedriver.chromium.org/downloads'
    base_driver_url = 'https://chromedriver.storage.googleapis.com/'
    file_name = 'chromedriver_' + get_platform_filename()
    driver_file_name = 'chromedriver' + '.exe' if platform == "win32" else ''
    pattern = 'https://.*?path=(\d+\.\d+\.\d+\.\d+)'

    # Download latest chromedriver.
    print('Finding latest chromedriver..')
    opener = urllib.request.FancyURLopener({})
    stream = opener.open(url)
    content = stream.read().decode('utf8')

    # Parse the latest version.
    match = re.search(pattern, content)
    if match and match.groups():
        # Url of download html page.
        url = match.group(0)
        # Version of latest driver.
        version = get_chrome_version()
        driver_url = base_driver_url + get_chrome_version() + '/' + file_name

        # Download the file.
        print('Version ' + version)
        print('Downloading ' + driver_url)
        app_path = os.path.dirname(os.path.realpath(__file__))
        chromedriver_path = app_path + '/' + driver_file_name
        file_path = app_path + '/' + file_name
        urllib.request.urlretrieve(driver_url, file_path)

        # Unzip the file.
        print('Unzipping ' + file_path)
        with zipfile.ZipFile(file_path, 'r') as zip_ref:
            zip_ref.extractall(app_path)

        print('Setting executable permission on ' + chromedriver_path)
        st = os.stat(chromedriver_path)
        os.chmod(chromedriver_path, st.st_mode | stat.S_IEXEC)

        # Cleanup.
        os.remove(file_path)

        result = True

    return result

def get_platform_filename():
    filename = ''

    is_64bits = sys.maxsize > 2**32

    if platform == "linux" or platform == "linux2":
        # linux
        filename += 'linux'
        filename += '64' if is_64bits else '32'
    elif platform == "darwin":
        # OS X
        filename += 'mac64'
    elif platform == "win32":
        # Windows...
        filename += 'win32'

    filename += '.zip'

    return filename


d = get_driver()        #just ro check the code..please diabel when using as a module
d.get('https://www.google.com')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment