Using Google Chrome Extensions with Selenium

By Evan Sangaline | November 20, 2017
Follow @sangaline

Running Google Chrome with an extension installed is quite simple because Chrome supports a --load-extension command-line argument for exactly this purpose. This can be specified before launching Chrome with Selenium by creating a ChromeOptions instance and calling add_argument().

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException


# Configure the necessary command-line option.
options = webdriver.ChromeOptions()
options.add_argument('--load-extension=path/to/the/extension')

# Initalize the driver with the appropriate options.
driver = webdriver.Chrome(chrome_options=options)

The above code will setup a Selenium driver for Chrome with the extension located at path/to/extension preinstalled.

Let’s make a very minimal Chrome extension and use it to verify that this code works. We’ll first need to make a directory to hold the extension

mkdir chrome-extension

and then we’ll need to create a manifest.json file inside of that directory to define the basic meta-information for the extension. Here’s a very basic example of a manifest.json file

{
  "manifest_version": 2,
  "name": "Chrome Extensions With Selenium",
  "version": "1.0.0",
  "content_scripts": [
    {
      "matches": ["*://*/*"],
      "js": ["content.js"],
      "run_at": "document_start"
    }
  ]
}

which includes only the minimum required fields and one content script. The content script is expected to be located in chrome-extension/content.js and it will be automatically injected into every page when the extension is installed. You can put whatever you want in here for web scraping or browser automation purposes, but here’s a useful piece of code for testing that Chrome is successfully loading the extension before launching.

// Wait for the DOM to completely load.
document.addEventListener("DOMContentLoaded", () => {
  // Overwrite the contents of the body.
  document.body.innerHTML = '<h1 id="installed" >Successfully Installed!</h1>';
});

This code will first wait for the DOM to load completely and will then replace the entire body of the document with a big banner saying “Successfully Installed!” We can write a simple test script for this that checks for the injected h1 tag and prints out a success or failure message.

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException


# Configure the necessary command-line option.
options = webdriver.ChromeOptions()
# Note that `chrome-extension` is the path to the unpackaged extension.
options.add_argument('--load-extension=chrome-extension')

# Navigate to any page... well, not just *any* page...
driver = webdriver.Chrome(chrome_options=options)
driver.get('https://intoli.com')

# Check if the extension worked and log the result.
try:
    header = driver.find_element_by_id('successfully-installed')
    print('Success! :-)')
except NoSuchElementException:
    print('Failure! :-(')
finally:
    # Clean up.
    driver.quit()

Running the script should output

Success! :-)

provided that everything is working correctly. The browser will quit automatically during the test, but you’ll like also see our success message flash briefly on the screen before that happens.

Successfully Installed!

Note that if you attempt to run this test in headless mode by adding an options.add_argument('--headless') line, you will unfortunately see the failure message.

Failure! :-(

This is because Google Chrome currently does not support Extensions in headless mode. If you have a use case for Chrome in headless mode then be sure to let the Chrome team know! It’s something that many of us would really love to see, and it will only happen if they get significant feedback about the issue.

Suggested Articles

If you enjoyed this article, then you might also enjoy these related ones.

Building Data Science Pipelines with Luigi and Jupyter Notebooks

By Mattia Ciollaro
on November 28, 2017

Learn about the Luigi task runner and how to use Jupyter notebooks in your workflows.

Read more

Dangerous Pickles — Malicious Python Serialization

By Evan Sangaline
on October 17, 2017

A light introduction to the Python pickle protocol, the Pickle Machine, and constructing malicious pickles.

Read more

A Brief Tour of Grouping and Aggregating in Pandas

By Andre Perunicic
on October 13, 2017

Learn how to use pandas to easily slice up a dataset and quickly extract useful statistics.

Read more

Comments