I'm using python-selenium and Chrome 59 and trying to automate a simple download sequence. When I launch the browser normally, the download works, but when I do so in headless mode, the download doesn't work.
# Headless implementation from selenium import webdriver chromeOptions = webdriver.ChromeOptions() chromeOptions.add_argument("headless") driver = webdriver.Chrome(chrome_options=chromeOptions) driver.get('https://www.mockaroo.com/') driver.find_element_by_id('download').click() # ^^^ Download doesn't start
# Normal Mode from selenium import webdriver driver = webdriver.Chrome() driver.get('https://www.mockaroo.com/') driver.find_element_by_id('download').click() # ^^^ Download works normally
I've even tried adding a default path:
prefs = {"download.default_directory" : "/Users/Chetan/Desktop/"} chromeOptions.add_argument("headless") chromeOptions.add_experimental_option("prefs",prefs)
Adding a default path works in the normal implementation, but the same problem persists in the headless version.
How do I get the download to start in headless mode?
Now the, the good news is Chromium team have officially announced the arrival of the functionality Downloading file through Headless Chromium .
Headless Browsers are Faster than Real Browsers But you will typically see a 2x to 15x faster performance when using a headless browser.
You can run Google Chrome in headless mode simply by setting the headless property of the chromeOptions object to True. Or, you can use the add_argument() method of the chromeOptions object to add the –headless command-line argument to run Google Chrome in headless mode using the Selenium Chrome web driver.
How to run Chrome in headless mode. In order to run your tests in headless mode, you will need to use the ChromeOptions as follows. ChromeOptions options = new ChromeOptions(); options. addArguments("--headless");
Yes, it's a "feature", for security. As mentioned before here is the bug discussion: https://bugs.chromium.org/p/chromium/issues/detail?id=696481
Support was added in chrome version 62.0.3196.0 or above to enable downloading.
Here is a python implementation. I had to add the command to the chromedriver commands. I will try to submit a PR so it is included in the library in the future.
def enable_download_in_headless_chrome(self, driver, download_dir): # add missing support for chrome "send_command" to selenium webdriver driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command') params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': download_dir}} command_result = driver.execute("send_command", params)
For reference here is a little repo to demonstrate how to use this: https://github.com/shawnbutton/PythonHeadlessChrome
update 2020-05-01 There have been comments saying this is not working anymore. Given this patch is now over a year old it's quite possible they have changed the underlying library.
Here's a working example for Python based on Shawn Button's answer. I've tested this with Chromium 68.0.3440.75 & chromedriver 2.38
from selenium import webdriver from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_experimental_option("prefs", { "download.default_directory": "/path/to/download/dir", "download.prompt_for_download": False, }) chrome_options.add_argument("--headless") driver = webdriver.Chrome(chrome_options=chrome_options) driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command') params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': "/path/to/download/dir"}} command_result = driver.execute("send_command", params) driver.get('http://download-page.url/') driver.find_element_by_css_selector("#download_link").click()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With