'Generic way to check browser options of running WebDriver instance

I have a generic method which eventually returns either a ChromeDriver or FirefoxDriver instance with the provided arguments as options, for example using ChromeDriver:

// Example using ChromeDriver, but also applies to FirefoxDriver
var options = new ChromeOptions();
options.AddArguments("foo", "bar", "headless");
return new ChromeDriver(options);

Now I want to test if the instance of the WebDriver actually has those provided arguments, but I haven't found a way to do this in a generic way.

I tried the following code to check if the provided arguments were stored in the browser capabilities, but I couldn't find them there using ChromeDriver.

// Using cast because of generic method
var capabilities = ((ChromeDriver)driver).Capabilities 

Headless mode

One of the options / arguments I want to check is running in headless mode. I can do this just fine for Chrome and Firefox.

To check headless mode for Chrome:

var userAgent = driver.ExecuteScript("return window.navigator.userAgent");

Which returns a string containing 'headless' when running in headless mode, and by using

var windowChrome = driver.ExecuteScript("return window.chrome");

Which returns null if running in headless mode, or an object if not running in headless.

But these methods don't work for Firefox, window.chrome obviously doesn't work, but when comparing the userAgents between non-headless and headless for Firefox they are exactly the same:

Non-headless mode

Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0

Headless mode

Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0

To check headless mode for Firefox, I could use this, but it's not available for other browsers

var headless = ((FirefoxDriver)driver).Capabilities.GetCapability("moz:headless");

I guess this shows how I can't rely on capabilities alone.


The examples above are just for checking headless mode, but I want to find a way to check different arguments provided by BrowserOptions in a generic way, after I created an instance of the WebDriver. If there's a way using JavaScript that's fine, but I prefer using just Selenium WebDriver.

This is an example how I currently check for headless mode, I want to be able to apply this to other BrowserOptions too, but I have to find them first :).

if (typeof(TWebDriver) == typeof(ChromeDriver))
    runsHeadless = driver.ExecuteScript<string>("return window.navigator.userAgent").ToLowerInvariant().Contains("headless");
else if (typeof(TWebDriver) == typeof(FirefoxDriver))
    runsHeadless = Convert.ToBoolean(((FirefoxDriver)driver).Capabilities.GetCapability("moz:headless"));
else
    throw new NotImplementedException($"WebDriver of type {typeof(TWebDriver)} is not yet supported.");

Assert.That(runsHeadless);


Solution 1:[1]

I know this is rather old, but when researching this myself I ended up here:

With Selenium 4 the following extension method works with for all desktop browsers that I am aware of as of February 2022:

/// <summary>
/// WebDriver Extensions
/// </summary>
public static class WebDriverExtensions
{
    /// <summary>
    /// <para> Is this WebDriver instance running Headless </para>
    /// <para> Caution this relies upon implementation details and is liable to breaking. </para>
    /// <para> See <cref>https://stackoverflow.com/questions/47559054/generic-way-to-check-browser-options-of-running-webdriver-instance</cref></para>
    /// </summary>
    /// <param name="driver"></param>
    /// <returns></returns>
    public static bool IsRunningHeadless(this IWebDriver driver)
    {
        // Check for Firefox headless flag
        var webDriver = driver as WebDriver;
        object firefoxHeadlessCapability = webDriver.Capabilities.GetCapability("moz:headless");
        if (firefoxHeadlessCapability != null &&
            firefoxHeadlessCapability.ToString()!.ToLower().Equals("true"))
        {
            return true;
        }

        // all other instances
        var jse = driver as IJavaScriptExecutor;
        var agent = jse.ExecuteScript("return window.navigator.userAgent").ToString();
        return agent.ToLower().Contains("headless");
    }
}

as only Firefox and Chromium based browsers can currently be requested headless - if neither approach returns true we can be confident that the browser is on screen.

Validated on: Firefox, Chrome, MS Edge, Safari, Internet Explorer (actual and Edge IE Mode)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alexander Oliveira Dunn