Headless mode is a useful way to run Firefox, which is just as it sounds — Firefox is run as normal, except without any of the UI components visible. This may not be very useful for surfing the web, but it is very useful for automated testing. This article provides all you need to know about running headless Firefox.

Using headless mode

This section provide usage instructions for headless mode.

Basic usage

You can run Firefox in headless mode from the command line, by including the -headless flag. For example:

/path/to/firefox -headless

Taking screenshots

Since Firefox 57, the -screenshot flag has allowed you to take screenshots of websites. The basic usage look like this:

/path/to/firefox -headless -screenshot https://developer.mozilla.com

This creates a full-height screenshot of https://developer.mozilla.com in the active directory called screenshot.png, with a viewport width of 800px.

Note that you can omit -headless when using -screenshot — it is implied:

/path/to/firefox -screenshot https://developer.mozilla.com

To override the default values mentioned above, you can use the following flags/features:

  • -screenshot name url — Set a custom name for the screenshot by including it between the -screenshot flag and the URL you want to capture. Note that you can specify other web-compatible image formats such as .jpg, .bmp, etc.
  • --window-size=x — Set a custom viewport width when taking the screenshot (full height is maintained). Note that the single argument version of this doesn't work.
  • --window-size=x,y — Set a custom viewport width and height to capture.

So for example, the following command creates a screenshot of https://developer.mozilla.com in the active directory called test.jpg, with a viewport width of 800px and a height of 1000px:

/path/to/firefox -screenshot test.jpg  https://developer.mozilla.com --window-size=480,1000

Browser support

Headless Firefox works on Fx55+ on Linux, and 56+ on Windows/Mac.

Automated testing with headless mode

The most useful way to use headless Firefox is to run automated tests with it, meaning that you can make your testing process much more efficient.

Selenium in Node.js

Here we'll create a Selenium test using Node.js and the selenium-webdriver package. For this guide we'll assume that you already have basic familiarity with Selenium, Webdriver, and Node, and that you already have a testing environment set up. If you don't, work through our Setting up Selenium in Node guide first, then come back.

First, of all, make sure you've got Node installed on your system, and the selenium-webdriver package installed, then create a new file called selenium-test.js and follow the steps below to populate it with test code.

Note: Alternatively, you could clone our headless-examples repo; this also includes a package file so you can just use npm install to install necessary dependencies.

  1. Let's add some code. Inside this file, start by importing the main selenium-webdriver module, and the firefox submodule:

    var webdriver = require('selenium-webdriver'),
        By = webdriver.By,
        until = webdriver.until;
    
    var firefox = require('selenium-webdriver/firefox');
  2. Next, we will create a new binary object representing Firefox Nightly, and add the -headless argument to it so that it will be run in headless mode:

    var binary = new firefox.Binary(firefox.Channel.NIGHTLY);
    binary.addArguments("-headless");
  3. Now let's create a new driver instance for Firefox, and use setFirefoxOptions() to include an options object that specifies that we want to run the test using the binary we created above (this step will be unnecessary on Linux, and after headless mode lands in the release channel on Windows/Mac, but it is still useful if you want to test a Nightly-specific feature):

    var driver = new webdriver.Builder()
        .forBrowser('firefox')
        .setFirefoxOptions(new firefox.Options().setBinary(binary))
        .build();
  4. Finally, add the following code, which performs a simple test on the Google search homepage:

    driver.get('https://www.google.com');
    driver.findElement(By.name('q')).sendKeys('webdriver');
    
    driver.sleep(1000).then(function() {
      driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    });
    
    driver.findElement(By.name('btnK')).click();
    
    driver.sleep(2000).then(function() {
      driver.getTitle().then(function(title) {
        if(title === 'webdriver - Google Search') {
          console.log('Test passed');
        } else {
          console.log('Test failed');
        }
      });
    });
    
    driver.quit();
  5. Finally, run your test with following command:

    node selenium-test

That's it! After a few seconds, you should see the message "Test passed" returned in the console.

Headless Firefox in Node.js with selenium-webdriver by Myk Melez contains additional useful tips and tricks for running Node.js Selenium tests with headless mode.

Selenium in Java

Note: Thanks a lot to nicholasdipiazza for writing these instructions!

This guide assumes that you already have Geckodriver on your machine, as explained in our Setting up Selenium in Node guide, and that you have an IDE set up that supports Gradle projects.

  1. Download our headlessfirefox-gradle.zip archive (see the source here), extract it, and import the headlessfirefox folder into your IDE as a gradle project.

  2. Edit the build.gradle file to set selenium to a later version if needed. At the time of writing, we used 3.5.3.

    group 'com.mozilla'
    version '1.0'
    
    apply plugin: 'java'
    
    sourceCompatibility = 1.8
    
    repositories {
       mavenCentral()
    }
    
    dependencies {
       compile('org.seleniumhq.selenium:selenium-api:3.5.3')
       compile('org.seleniumhq.selenium:selenium-remote-driver:3.5.3')
       compile('org.seleniumhq.selenium:selenium-server:3.5.3')
    
       testCompile group: 'junit', name: 'junit', version: '4.12'
    }
  3. Edit the webdriver.gecko.driver property in the HeadlessFirefoxSeleniumExample.java file to equal the path where you installed geckodriver (see line 15 below).

    package com.mozilla.example;
    
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.firefox.FirefoxBinary;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.firefox.FirefoxOptions;
    
    import java.util.concurrent.TimeUnit;
    
    public class HeadlessFirefoxSeleniumExample {
     public static void main(String [] args) {
       FirefoxBinary firefoxBinary = new FirefoxBinary();
       firefoxBinary.addCommandLineOptions("--headless");
       System.setProperty("webdriver.gecko.driver", "/opt/geckodriver");
       FirefoxOptions firefoxOptions = new FirefoxOptions();
       firefoxOptions.setBinary(firefoxBinary);
       FirefoxDriver driver = new FirefoxDriver(firefoxOptions);
       try {
         driver.get("http://www.google.com");
         driver.manage().timeouts().implicitlyWait(4,
             TimeUnit.SECONDS);
         WebElement queryBox = driver.findElement(By.name("q"));
         queryBox.sendKeys("headless firefox");
         WebElement searchBtn = driver.findElement(By.name("btnK"));
         searchBtn.click();
         WebElement iresDiv = driver.findElement(By.id("ires"));
         iresDiv.findElements(By.tagName("a")).get(0).click();
         System.out.println(driver.getPageSource());
       } finally {
         driver.quit();
       }
     }
    }
  4. Run the java class and you should see the HTML content of this page printed in your console/terminal.

Selenium in Python

This guide assumes that you already have geckodriver on your machine, as explained in our Setting up Selenium in Node guide.

  1. Install the latest version of the Python client for Selenium.

  2. Edit the following to set the executable_path on line 11 to the path were you installed geckodriver.

    from selenium.webdriver import Firefox
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.firefox.options import Options
    from selenium.webdriver.support import expected_conditions as expected
    from selenium.webdriver.support.wait import WebDriverWait
    
    if __name__ == "__main__":
        options = Options()
        options.add_argument('-headless')
        driver = Firefox(executable_path='geckodriver', firefox_options=options)
        wait = WebDriverWait(driver, timeout=10)
        driver.get('http://www.google.com')
        wait.until(expected.visibility_of_element_located((By.NAME, 'q'))).send_keys('headless firefox' + Keys.ENTER)
        wait.until(expected.visibility_of_element_located((By.CSS_SELECTOR, '#ires a'))).click()
        print(driver.page_source)
        driver.quit()
  3. Run the Python script and you should see the HTML content of this page printed in your console/terminal.

Other testing solutions

  • Slimerjs has Firefox support built in on Linux, with Mac and Windows support coming soon. See Headless SlimerJS with Firefox by Brendan Dahl for more details.
  • TestCafe (v.0.18.0 and higher) also supports testing in headless Firefox out of the box. See the documentation for the details.

In addition, you will be able to use headless Firefox to run automated tests written in most other popular testing apps, as long as they allow you to set environment variables.

Troubleshooting and further help

If you are having trouble getting headless mode to work, then do not worry — we are here to help. This section is designed to be added to as more questions arise and answers are found.

  • On Linux, certain libraries are currently required on your system even though headless mode doesn't use them — because Firefox links against them. See bug 1372998 for more details and progress towards a fix.

If you want to ask the engineers a question, the best place to go is the #headless channel on Mozilla IRC. If you are pretty sure you've found a bug, file it on Mozilla Bugzilla.

See also

Document Tags and Contributors

 Contributors to this page: davehunt, Nuarat, chrisdavidmills, stlk, Vinnl, Sheppy, Dholbert
 Last updated by: davehunt,