Selenium can't find element on Linux headless, but it can on Windows headless?

I am running Selenium headless on a Linux machine, and it can't find a specific element. However, I run the same exact code on a Windows machine and it finds the element without a problem. I have the latest version of the driver on my Linux machine. Any ideas how to fix this?

options = Options()
options.add_argument('--no-sandbox')
options.add_argument("--headless")
options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                     'Chrome/97.0.4692.71 Safari/537.36')
with webdriver.Chrome(options=options) as driver:
    driver.get(url)
    driver.find_element(By.ID, "btnhome").click()
    video = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.TAG_NAME, "video"))).get_attribute("src")

The problem element is the video element. I have increased the wait time to 2 minutes as well, just for debugging. It works fine on Windows headless, but can't find it on Linux headless.

Thanks


The solution for this involves using https://github.com/ponty/PyVirtualDisplay in order to simulate a headed display in a headless environment such as Linux. (This can help you get around issues that might only appear when loading a website with a headless browser.) The virtual display uses Xvfb, and there's actually a very popular Stack Overflow solution here about it: https://stackoverflow.com/a/6300672

Here's a summary of the previous solution for your situation:

To install:

pip install pyvirtualdisplay

And here's how to use it in your Python code:

from pyvirtualdisplay import Display
display = Display(visible=0, size=(800, 600))
display.start()
# display is active / Run your selenium code
# ----------
display.stop()
# display is stopped

After putting it all together with your code, it will look something like this:

from pyvirtualdisplay import Display
display = Display(visible=0, size=(800, 600))
display.start()
# ...
options = Options()
options.add_argument('--no-sandbox')
options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                     'Chrome/97.0.4692.71 Safari/537.36')
with webdriver.Chrome(options=options) as driver:
    driver.get(url)
    driver.find_element(By.ID, "btnhome").click()
    video = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.TAG_NAME, "video"))).get_attribute("src")
# ...
display.stop()

(Make modifications as necessary, such as the screen resolution, etc.)

There are some Selenium Python frameworks that already have the virtual display built-in (such as SeleniumBase, which activates the virtual display via an added pytest command-line arg: --xvfb.) Each framework that has the feature built-in may do things a bit differently.