Contents

    Guides

    Why Test Chrome Extensions on Real Devices with Selenium

    Published on

    September 29, 2025
    Why Test Chrome Extensions on Real Devices with Selenium

    Chrome extensions are widely used to enhance browser functionality, automate tasks, and integrate with third-party services. 

    The Chrome Web Store hosts over 180,000 extensions, ranging from password managers to developer utilities. For testers, ensuring these extensions work correctly is critical. Selenium WebDriver provides the flexibility to load and automate Chrome extensions, making it a preferred choice for validating extension workflows.

    What is a Chrome Extension — Packed vs Unpacked?

    Chrome extensions come in two formats:

    • Packed extensions (CRX files): Distributed through the Chrome Web Store or as standalone .crx files. These are compressed and digitally signed.
    • Unpacked extensions (directory form): A folder containing manifest and source files (HTML, JS, CSS, JSON). Useful for debugging and development.

    Selenium supports both formats, allowing testers to load extensions during browser initialization.

    Why Automate Chrome Extensions with Selenium?

    Automating Chrome extensions enables teams to:

    • Verify UI and functionality across versions of Chrome.
    • Ensure extension compatibility with web applications.
    • Detect issues caused by background scripts, popups, or permissions.
    • Run regression tests to validate extension updates before release.

    Without automation, extension testing becomes time-consuming and error-prone, especially for extensions that rely on background APIs or dynamically injected scripts.

    Prerequisites

    Matching ChromeDriver and Chrome Versions

    Selenium tests rely on ChromeDriver to communicate with the Chrome browser. ChromeDriver must match the major version of Chrome installed. Mismatched versions can cause startup failures, unrecognized commands, or silent crashes.

    Selenium

    Ensure that Selenium WebDriver is installed and up to date. For Java, add the Maven dependency. For Python, install via pip:

    pip install selenium

    Having the Extension Files: CRX / Directory

    Keep the extension ready either as a .crx file or as an unpacked folder with a manifest. For testing unreleased or custom extensions, the unpacked directory is recommended.

    Setting Up Selenium with Chrome Extensions

    Using ChromeOptions to install extensions (packed or unpacked)

    Selenium’s ChromeOptions class allows extensions to be loaded at startup.

    Java Example (Packed Extension):

    ChromeOptions options = new ChromeOptions();

    options.addExtensions(new File("path/to/extension.crx"));

    WebDriver driver = new ChromeDriver(options);

    Python Example (Unpacked Extension):

    from selenium import webdriver

    options = webdriver.ChromeOptions()

    options.add_argument("load-extension=/path/to/unpacked/extension")

    driver = webdriver.Chrome(options=options)

    Loading extensions at startup with arguments (e.g. load-extension)

    The --load-extension argument is used for unpacked extensions. Multiple extensions can be loaded by providing a comma-separated list of directories.

    options.add_argument("load-extension=/ext1,/ext2")

    Accessing Extension UI and Pages

    Navigating to extension pages (popup, options) via chrome-extension:// URLs

    Every extension has a unique ID. With it, testers can navigate to the options page:

    driver.get("chrome-extension://<extension-id>/options.html")

    Popups can be handled by simulating clicks on the extension icon and switching to the new window context.

    Handling frames / popups / background pages

    Some extensions inject iframes or open separate popup windows. Selenium allows switching contexts:

    driver.switch_to.frame("frameName")

    driver.switch_to.window(driver.window_handles[-1])

    Interacting with the Chrome Extension in Tests

    Using WebDriver to click UI elements inside extension popups or options pages

    Once inside the extension’s context, regular Selenium locators (By.id, By.cssSelector) can be used to interact with input fields, buttons, and toggles.

    Managing shadow DOM inside extension manager or extension pages

    Some extensions use Shadow DOM for encapsulated UI. Selenium requires JavaScript execution to pierce through Shadow DOM:

    shadow_root = driver.execute_script(

      "return document.querySelector('custom-element').shadowRoot"

    )

    button = shadow_root.find_element_by_css_selector('button.save')

    button.click()

    Configuring Extension Settings Programmatically

    Extensions often store settings in localStorage, chrome.storage, or config files. Selenium can manipulate these through JavaScript execution:

    driver.execute_script("localStorage.setItem('theme', 'dark')")

    For advanced testing, APIs like chrome.storage.sync can be stubbed or verified through direct script injection.

    Challenges and Limitations

    Permissions and security restrictions

    Some APIs require explicit permissions. Extensions with blocked APIs may not load in automated runs, especially in headless Chrome.

    Asynchronous loading or delayed initialization of extension scripts

    Background scripts may take time to initialize. Testers must add explicit waits to handle delayed content rendering.

    CI / Remote execution issues

    Extensions may fail in CI pipelines where Chrome runs in headless mode. Additional flags like --disable-extensions-except and --load-extension help mitigate issues.

    Best Practices for Reliable Extension Testing

    Here are some of the best practices for reliable extension testing:

    • Always pin ChromeDriver to a stable version to prevent unexpected failures.
    • Use explicit waits for extension pages that rely on async APIs.
    • Separate tests for extension-specific functionality vs general web UI.
    • Validate extension behavior on multiple OS environments.

    Example Code Snippets in Multiple Languages

    Java:

    ChromeOptions options = new ChromeOptions();

    options.addExtensions(new File("myExtension.crx"));

    WebDriver driver = new ChromeDriver(options);

    driver.get("chrome-extension://id/options.html");

    Python:

    options = webdriver.ChromeOptions()

    options.add_argument("load-extension=/path/to/unpacked")

    driver = webdriver.Chrome(options=options)

    driver.get("chrome-extension://id/popup.html")

    JavaScript (Node.js with Selenium WebDriver):

    const {Builder} = require('selenium-webdriver');

    const chrome = require('selenium-webdriver/chrome');

    let options = new chrome.Options();

    options.addArguments("load-extension=/path/to/unpacked");

    let driver = new Builder().forBrowser('chrome').setChromeOptions(options).build();

    await driver.get("chrome-extension://id/options.html");

    Why use Real Devices to Test Chrome Extensions?

    Running Selenium tests for Chrome extensions locally is useful for initial validation, but it rarely replicates the diversity of real-world environments. Extensions often behave differently depending on operating system settings, Chrome version, or hardware configurations. For example, a popup that loads correctly on Windows might fail on macOS due to differences in permissions or rendering engines. Similarly, headless environments used in CI pipelines may not support certain extension APIs at all, leading to false positives or incomplete coverage.

    Testing on real devices helps ensure that:

    • Extensions load and function properly across different OS versions (Windows, macOS, Linux).
    • Browser-specific quirks in Chrome builds are identified early.
    • Interactions with background pages, popups, and shadow DOM are validated under realistic conditions.
    • Network restrictions, security prompts, and system-level permission dialogs do not break workflows.

    Instead of setting up and maintaining multiple test environments manually, teams can use BrowserStack Automate to execute Selenium tests for Chrome extensions on a wide range of real devices and browsers in the cloud. Automate allows extensions to be loaded through ChromeOptions during remote execution, ensuring the same workflows run consistently across environments. This eliminates the overhead of local infrastructure while delivering reliable, production-grade test results.

    Conclusion

    Automating Chrome extensions with Selenium enables comprehensive validation of extension workflows, from popups to background scripts. By handling permissions, managing frames, and addressing asynchronous loading, testers can build reliable automation suites. Running these tests on real devices ensures coverage across diverse environments, reducing risk before release.

    Run Selenium Tests on Cloud

    Data-rich bug reports loved by everyone

    Get visual proof, steps to reproduce and technical logs with one click

    Make bug reporting 50% faster and 100% less painful

    Rating LogosStars
    4.6
    |
    Category leader

    Liked the article? Spread the word

    Put your knowledge to practice

    Try Bird on your next bug - you’ll love it

    “Game changer”

    Julie, Head of QA

    star-ratingstar-ratingstar-ratingstar-ratingstar-rating

    Overall rating: 4.7/5

    Try Bird later, from your desktop