Selenium Webdriver – Disabling Chrome Logging Messages

This is a quick post, but took a little digging to come up with the solution featured.

The Issue

The issue, which you can find many users complaining about, is that when using Chrome as the browser with Selenium Webdriver and NodeJS, the default log preferences don’t seem to be respected and messages still appear in the console / stdout.

To start with, it seems at first as though it is impossible to get rid of this log message: “DevTools listening on ws://....” when first connecting.

To be clear, even if you explicitly tell Selenium that you want all logging off, you will still get this message. My first attempt tried to use this approach and failed:

const wdLogging = require('selenium-webdriver/lib/logging');
const loggingPrefs = new wdLogging.Preferences();
for (const logType in wdLogging.Type) {
    loggingPrefs.setLevel(logType, wdLogging.Level.OFF);
}

// I still got messages after creating a webdriver instance with these preferences

Solution

The solution involves the use of excludeSwitches – these are switches / flags that you want to exclude ChromeDriver from including by default. So, anything passed through excludeSwitches basically negates / removes a flag normally set as true by ChromeDriver.

Turns out, ChromeDriver has a default switch that enables logging – --enable-logging; you need to pass this to Selenium to turn it off. I found this via this S/O answer and the linked ChromeDriver Issue.

A concise example of adding the switch is this:

const { Options } = require('selenium-webdriver/chrome');
const chromeOptions = new Options();
chromeOptions.excludeSwitches('enable-logging');

But, for a full copy-and-paste example, here is working code:

// @ts-check
const path = require('path');
const { ServiceBuilder, Options: ChromeOptions } = require('selenium-webdriver/chrome');
const webdriver = require('selenium-webdriver');

async function main() {
    // I'm doing this because I hate adding things to my PATH 😅
    // Normally, webdriver will automatically grab the EXE from PATH if you have followed a generic setup guide
    const driverBinPath = path.normalize(`C:\\Users\\Joshua\\Downloads\\chromedriver_win32\\chromedriver.exe`);
    const serviceBuilder = new ServiceBuilder(driverBinPath);

    /**
     * SOLUTION:
     * By excluding the switch from defaults, this should disable the default logging
     * @see https://bugs.chromium.org/p/chromedriver/issues/detail?id=2907#c3
     */
    const chromeOptions = new ChromeOptions();
    chromeOptions.excludeSwitches('enable-logging');

    // Put everything together
    const driver = await new webdriver.Builder()
        .forBrowser('chrome')
        .setChromeService(serviceBuilder)
        .setChromeOptions(chromeOptions)
        .build();

    // Let's try something
    await driver.get(`https://example.com`);
    const title = await driver.getTitle();
    return title;
}

main().then(console.log);

You can also find the source code pasted into this Github Gist.

Other Languages

Since Selenium supports a lot of different programming languages, I’m not going to post the full code for each one, but the solution should still be the same, as long as Selenium is passing excludeSwitches through for that implementation.

For example, in Python, the main difference would be changing:

// NodeJS Code
const { Options } = require('selenium-webdriver/chrome');
const chromeOptions = new Options();
chromeOptions.excludeSwitches('enable-logging');

… to:

# Python Code
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])

Some More Background

I didn’t want to spend too much time digging into this, but my guess at why this behavior was introduced and past logging options no longer works is that the new flag probably overrides any granular settings, such as the old solution of --log-level-3.

It is also important to note that ChromeDriver is a completely separate project from Selenium Webdriver; part of why it took me a bit to find the solution is because I kept searching Selenium’s source code for text that was too specific to ChromeDriver – ChromeDriver itself actually lives in the Google chromium mono-repo.

There might be other solutions out there, but this one worked for me! Feel free to let me know if you find differently!

Leave a Reply

Your email address will not be published. Required fields are marked *