---
title: Headless Cloud Testing with Selenium on Firefox, Chrome and Edge
description: Run headless browser tests with Selenium WebDriver on Chrome, Firefox
  and Edge. Faster test execution with headless browser testing on TestingBot's cloud
  infrastructure.
source_url:
  html: https://testingbot.com/support/web-automate/headless
  md: https://testingbot.com/support/web-automate/headless/index.md
---
# Headless Testing Documentation

Headless testing **significantly minimizes the time it takes to run a test**. Because the browser runs in headless mode, it is not necessary to render the graphical user interface.

This means the browser starts faster and uses less resources, resulting in quicker test execution.

You can still take screenshots during headless mode. Video recording of the test however is not available in headless mode.

## Chrome Headless Testing

To run headless tests on Chrome, simply set `headless: true` in `tb:options`. This tells TestingBot to launch the browser in headless mode and automatically disables video recording.

We recommend using the `LINUX` platform for the fastest headless testing experience.

[Java](https://testingbot.com#)[Python](https://testingbot.com#)[NodeJS](https://testingbot.com#)[WebdriverIO](https://testingbot.com#)[Ruby](https://testingbot.com#)[C#](https://testingbot.com#)[PHP](https://testingbot.com#)[Robot Framework](https://testingbot.com#)

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.chrome.ChromeOptions;
    import org.openqa.selenium.remote.RemoteWebDriver;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    
    public class HeadlessChromeTest {
        public static void main(String[] args) throws Exception {
            ChromeOptions chromeOptions = new ChromeOptions();
            chromeOptions.setPlatformName("LINUX");
            chromeOptions.setBrowserVersion("latest");
    
            Map<String, Object> tbOptions = new HashMap<>();
            tbOptions.put("key", "API_KEY");
            tbOptions.put("secret", "API_SECRET");
            tbOptions.put("name", "Chrome Headless Test");
            tbOptions.put("headless", true);
    
            chromeOptions.setCapability("tb:options", tbOptions);
    
            WebDriver driver = new RemoteWebDriver(
                new URL("https://hub.testingbot.com/wd/hub"),
                chromeOptions
            );
    
            driver.get("https://www.google.com");
            System.out.println("Title: " + driver.getTitle());
            driver.quit();
        }
    }

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    chrome_options = Options()
    chrome_options.set_capability("platformName", "LINUX")
    chrome_options.set_capability("browserVersion", "latest")
    chrome_options.set_capability("tb:options", {
        "key": "API_KEY",
        "secret": "API_SECRET",
        "name": "Chrome Headless Test",
        "headless": True
    })
    
    driver = webdriver.Remote(
        command_executor="https://hub.testingbot.com/wd/hub",
        options=chrome_options
    )
    
    driver.get("https://www.google.com")
    print("Title:", driver.title)
    driver.quit()

    const { Builder } = require('selenium-webdriver');
    
    async function runHeadlessTest() {
        const driver = await new Builder()
            .forBrowser('chrome')
            .withCapabilities({
                'browserName': 'chrome',
                'browserVersion': 'latest',
                'platformName': 'LINUX',
                'tb:options': {
                    'key': 'API_KEY',
                    'secret': 'API_SECRET',
                    'name': 'Chrome Headless Test',
                    'headless': true
                }
            })
            .usingServer('https://hub.testingbot.com/wd/hub')
            .build();
    
        try {
            await driver.get('https://www.google.com');
            const title = await driver.getTitle();
            console.log('Title:', title);
        } finally {
            await driver.quit();
        }
    }
    
    runHeadlessTest();

    // wdio.conf.js
    exports.config = {
        user: 'API_KEY',
        key: 'API_SECRET',
    
        capabilities: [{
            browserName: 'chrome',
            browserVersion: 'latest',
            platformName: 'LINUX',
            'tb:options': {
                name: 'Chrome Headless Test',
                headless: true
            }
        }],
    
        services: [['testingbot']],
    
        // Your test configuration
        specs: ['./test/specs/**/*.js'],
        framework: 'mocha',
        reporters: ['spec']
    };
    
    // test/specs/example.js
    describe('Headless Chrome Test', () => {
        it('should load Google', async () => {
            await browser.url('https://www.google.com');
            const title = await browser.getTitle();
            console.log('Title:', title);
        });
    });

    require 'selenium-webdriver'
    
    options = Selenium::WebDriver::Chrome::Options.new
    options.platform_name = 'LINUX'
    options.browser_version = 'latest'
    
    caps = Selenium::WebDriver::Remote::Capabilities.new(
      'tb:options': {
        key: 'API_KEY',
        secret: 'API_SECRET',
        name: 'Chrome Headless Test',
        headless: true
      }
    )
    
    driver = Selenium::WebDriver.for(
      :remote,
      url: 'https://hub.testingbot.com/wd/hub',
      capabilities: [options, caps]
    )
    
    driver.get('https://www.google.com')
    puts "Title: #{driver.title}"
    driver.quit

    using OpenQA.Selenium;
    using OpenQA.Selenium.Chrome;
    using OpenQA.Selenium.Remote;
    
    var chromeOptions = new ChromeOptions();
    chromeOptions.PlatformName = "LINUX";
    chromeOptions.BrowserVersion = "latest";
    
    var tbOptions = new Dictionary<string, object>
    {
        ["key"] = "API_KEY",
        ["secret"] = "API_SECRET",
        ["name"] = "Chrome Headless Test",
        ["headless"] = true
    };
    
    chromeOptions.AddAdditionalOption("tb:options", tbOptions);
    
    IWebDriver driver = new RemoteWebDriver(
        new Uri("https://hub.testingbot.com/wd/hub"),
        chromeOptions.ToCapabilities(),
        TimeSpan.FromSeconds(600)
    );
    
    driver.Navigate().GoToUrl("https://www.google.com");
    Console.WriteLine("Title: " + driver.Title);
    driver.Quit();

    <?php
    require_once('vendor/autoload.php');
    
    use Facebook\WebDriver\Remote\RemoteWebDriver;
    use Facebook\WebDriver\Remote\DesiredCapabilities;
    
    $capabilities = DesiredCapabilities::chrome();
    $capabilities->setCapability('browserVersion', 'latest');
    $capabilities->setCapability('platformName', 'LINUX');
    $capabilities->setCapability('tb:options', [
        'key' => 'API_KEY',
        'secret' => 'API_SECRET',
        'name' => 'Chrome Headless Test',
        'headless' => true
    ]);
    
    $driver = RemoteWebDriver::create(
        'https://hub.testingbot.com/wd/hub',
        $capabilities,
        60000,
        60000
    );
    
    $driver->get('https://www.google.com');
    echo "Title: " . $driver->getTitle() . "\n";
    $driver->quit();
    ?>

Save the example below in a `headless_chrome.robot` file:

    ***Settings***
    Library SeleniumLibrary
    Library TestingBot
    Library Collections
    
    Test Setup Open Headless Chrome Browser
    Test Teardown Close Test Browser
    
    ***Variables***
    ${TB_KEY} API_KEY
    ${TB_SECRET} API_SECRET
    
    ***Test Cases***
    Chrome Headless Test
        Go To https://www.google.com
        Title Should Be Google
    
    ***Keywords***
    Open Headless Chrome Browser
        ${chrome_options}= Evaluate selenium.webdriver.ChromeOptions() modules=selenium.webdriver
    
        # Set W3C capabilities
        Call Method ${chrome_options} set_capability platformName LINUX
        Call Method ${chrome_options} set_capability browserVersion latest
    
        # Set TestingBot options with headless enabled
        ${tb_options}= Create Dictionary name=Chrome Headless Test headless=${True}
        Call Method ${chrome_options} set_capability tb:options ${tb_options}
    
        Open Browser about:blank
        ... remote_url=https://${TB_KEY}:${TB_SECRET}@hub.testingbot.com/wd/hub
        ... options=${chrome_options}
    
    Close Test Browser
        Report TestingBot Status
        ... ${SUITE_NAME} | ${TEST_NAME}
        ... ${TEST_STATUS}
        ... ${TB_KEY}:${TB_SECRET}
        Close All Browsers

Save the code below in a `TestingBot.py` file:

    import requests
    from robot.libraries.BuiltIn import BuiltIn
    
    def report_testingbot_status(name, status, credentials):
        selenium = BuiltIn().get_library_instance('SeleniumLibrary')
        session_id = selenium.driver.session_id
    
        payload = {'test[name]': name, 'test[success]': int(status == 'PASS')}
        key, secret = credentials.split(':')
    
        url = 'https://api.testingbot.com/v1/tests/{0}'.format(session_id)
        response = requests.put(url, data=payload, auth=(key, secret))
        assert response.status_code == 200, response.text

To run the test:

    pip install robotframework-seleniumlibrary requests
    PYTHONPATH=$PYTHONPATH:. robot headless_chrome.robot

## Firefox Headless Testing

To run headless tests on Firefox, simply set `headless: true` in `tb:options`. This tells TestingBot to launch the browser in headless mode and automatically disables video recording.

[Java](https://testingbot.com#)[Python](https://testingbot.com#)[NodeJS](https://testingbot.com#)[WebdriverIO](https://testingbot.com#)[Ruby](https://testingbot.com#)[C#](https://testingbot.com#)[PHP](https://testingbot.com#)[Robot Framework](https://testingbot.com#)

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.firefox.FirefoxOptions;
    import org.openqa.selenium.remote.RemoteWebDriver;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    
    public class HeadlessFirefoxTest {
        public static void main(String[] args) throws Exception {
            FirefoxOptions firefoxOptions = new FirefoxOptions();
            firefoxOptions.setPlatformName("LINUX");
            firefoxOptions.setBrowserVersion("latest");
    
            Map<String, Object> tbOptions = new HashMap<>();
            tbOptions.put("key", "API_KEY");
            tbOptions.put("secret", "API_SECRET");
            tbOptions.put("name", "Firefox Headless Test");
            tbOptions.put("headless", true);
    
            firefoxOptions.setCapability("tb:options", tbOptions);
    
            WebDriver driver = new RemoteWebDriver(
                new URL("https://hub.testingbot.com/wd/hub"),
                firefoxOptions
            );
    
            driver.get("https://www.google.com");
            System.out.println("Title: " + driver.getTitle());
            driver.quit();
        }
    }

    from selenium import webdriver
    from selenium.webdriver.firefox.options import Options
    
    firefox_options = Options()
    firefox_options.set_capability("platformName", "LINUX")
    firefox_options.set_capability("browserVersion", "latest")
    firefox_options.set_capability("tb:options", {
        "key": "API_KEY",
        "secret": "API_SECRET",
        "name": "Firefox Headless Test",
        "headless": True
    })
    
    driver = webdriver.Remote(
        command_executor="https://hub.testingbot.com/wd/hub",
        options=firefox_options
    )
    
    driver.get("https://www.google.com")
    print("Title:", driver.title)
    driver.quit()

    const { Builder } = require('selenium-webdriver');
    
    async function runHeadlessTest() {
        const driver = await new Builder()
            .forBrowser('firefox')
            .withCapabilities({
                'browserName': 'firefox',
                'browserVersion': 'latest',
                'platformName': 'LINUX',
                'tb:options': {
                    'key': 'API_KEY',
                    'secret': 'API_SECRET',
                    'name': 'Firefox Headless Test',
                    'headless': true
                }
            })
            .usingServer('https://hub.testingbot.com/wd/hub')
            .build();
    
        try {
            await driver.get('https://www.google.com');
            const title = await driver.getTitle();
            console.log('Title:', title);
        } finally {
            await driver.quit();
        }
    }
    
    runHeadlessTest();

    // wdio.conf.js
    exports.config = {
        user: 'API_KEY',
        key: 'API_SECRET',
    
        capabilities: [{
            browserName: 'firefox',
            browserVersion: 'latest',
            platformName: 'LINUX',
            'tb:options': {
                name: 'Firefox Headless Test',
                headless: true
            }
        }],
    
        services: [['testingbot']],
    
        // Your test configuration
        specs: ['./test/specs/**/*.js'],
        framework: 'mocha',
        reporters: ['spec']
    };
    
    // test/specs/example.js
    describe('Headless Firefox Test', () => {
        it('should load Google', async () => {
            await browser.url('https://www.google.com');
            const title = await browser.getTitle();
            console.log('Title:', title);
        });
    });

    require 'selenium-webdriver'
    
    options = Selenium::WebDriver::Firefox::Options.new
    options.platform_name = 'LINUX'
    options.browser_version = 'latest'
    
    caps = Selenium::WebDriver::Remote::Capabilities.new(
      'tb:options': {
        key: 'API_KEY',
        secret: 'API_SECRET',
        name: 'Firefox Headless Test',
        headless: true
      }
    )
    
    driver = Selenium::WebDriver.for(
      :remote,
      url: 'https://hub.testingbot.com/wd/hub',
      capabilities: [options, caps]
    )
    
    driver.get('https://www.google.com')
    puts "Title: #{driver.title}"
    driver.quit

    using OpenQA.Selenium;
    using OpenQA.Selenium.Firefox;
    using OpenQA.Selenium.Remote;
    
    var firefoxOptions = new FirefoxOptions();
    firefoxOptions.PlatformName = "LINUX";
    firefoxOptions.BrowserVersion = "latest";
    
    var tbOptions = new Dictionary<string, object>
    {
        ["key"] = "API_KEY",
        ["secret"] = "API_SECRET",
        ["name"] = "Firefox Headless Test",
        ["headless"] = true
    };
    
    firefoxOptions.AddAdditionalOption("tb:options", tbOptions);
    
    IWebDriver driver = new RemoteWebDriver(
        new Uri("https://hub.testingbot.com/wd/hub"),
        firefoxOptions.ToCapabilities(),
        TimeSpan.FromSeconds(600)
    );
    
    driver.Navigate().GoToUrl("https://www.google.com");
    Console.WriteLine("Title: " + driver.Title);
    driver.Quit();

    <?php
    require_once('vendor/autoload.php');
    
    use Facebook\WebDriver\Remote\RemoteWebDriver;
    use Facebook\WebDriver\Remote\DesiredCapabilities;
    
    $capabilities = DesiredCapabilities::firefox();
    $capabilities->setCapability('browserVersion', 'latest');
    $capabilities->setCapability('platformName', 'LINUX');
    $capabilities->setCapability('tb:options', [
        'key' => 'API_KEY',
        'secret' => 'API_SECRET',
        'name' => 'Firefox Headless Test',
        'headless' => true
    ]);
    
    $driver = RemoteWebDriver::create(
        'https://hub.testingbot.com/wd/hub',
        $capabilities,
        60000,
        60000
    );
    
    $driver->get('https://www.google.com');
    echo "Title: " . $driver->getTitle() . "\n";
    $driver->quit();
    ?>

Save the example below in a `headless_firefox.robot` file:

    ***Settings***
    Library SeleniumLibrary
    Library TestingBot
    Library Collections
    
    Test Setup Open Headless Firefox Browser
    Test Teardown Close Test Browser
    
    ***Variables***
    ${TB_KEY} API_KEY
    ${TB_SECRET} API_SECRET
    
    ***Test Cases***
    Firefox Headless Test
        Go To https://www.google.com
        Title Should Be Google
    
    ***Keywords***
    Open Headless Firefox Browser
        ${firefox_options}= Evaluate selenium.webdriver.FirefoxOptions() modules=selenium.webdriver
    
        # Set W3C capabilities
        Call Method ${firefox_options} set_capability platformName LINUX
        Call Method ${firefox_options} set_capability browserVersion latest
    
        # Set TestingBot options with headless enabled
        ${tb_options}= Create Dictionary name=Firefox Headless Test headless=${True}
        Call Method ${firefox_options} set_capability tb:options ${tb_options}
    
        Open Browser about:blank
        ... remote_url=https://${TB_KEY}:${TB_SECRET}@hub.testingbot.com/wd/hub
        ... options=${firefox_options}
    
    Close Test Browser
        Report TestingBot Status
        ... ${SUITE_NAME} | ${TEST_NAME}
        ... ${TEST_STATUS}
        ... ${TB_KEY}:${TB_SECRET}
        Close All Browsers

Save the code below in a `TestingBot.py` file:

    import requests
    from robot.libraries.BuiltIn import BuiltIn
    
    def report_testingbot_status(name, status, credentials):
        selenium = BuiltIn().get_library_instance('SeleniumLibrary')
        session_id = selenium.driver.session_id
    
        payload = {'test[name]': name, 'test[success]': int(status == 'PASS')}
        key, secret = credentials.split(':')
    
        url = 'https://api.testingbot.com/v1/tests/{0}'.format(session_id)
        response = requests.put(url, data=payload, auth=(key, secret))
        assert response.status_code == 200, response.text

To run the test:

    pip install robotframework-seleniumlibrary requests
    PYTHONPATH=$PYTHONPATH:. robot headless_firefox.robot

## Microsoft Edge Headless Testing

To run headless tests on Microsoft Edge, simply set `headless: true` in `tb:options`. This tells TestingBot to launch the browser in headless mode and automatically disables video recording.

We recommend using the `WIN11` platform for Edge headless testing.

[Java](https://testingbot.com#)[Python](https://testingbot.com#)[NodeJS](https://testingbot.com#)[WebdriverIO](https://testingbot.com#)[Ruby](https://testingbot.com#)[C#](https://testingbot.com#)[PHP](https://testingbot.com#)[Robot Framework](https://testingbot.com#)

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.edge.EdgeOptions;
    import org.openqa.selenium.remote.RemoteWebDriver;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    
    public class HeadlessEdgeTest {
        public static void main(String[] args) throws Exception {
            EdgeOptions edgeOptions = new EdgeOptions();
            edgeOptions.setPlatformName("WIN11");
            edgeOptions.setBrowserVersion("latest");
    
            Map<String, Object> tbOptions = new HashMap<>();
            tbOptions.put("key", "API_KEY");
            tbOptions.put("secret", "API_SECRET");
            tbOptions.put("name", "Edge Headless Test");
            tbOptions.put("headless", true);
    
            edgeOptions.setCapability("tb:options", tbOptions);
    
            WebDriver driver = new RemoteWebDriver(
                new URL("https://hub.testingbot.com/wd/hub"),
                edgeOptions
            );
    
            driver.get("https://www.google.com");
            System.out.println("Title: " + driver.getTitle());
            driver.quit();
        }
    }

    from selenium import webdriver
    from selenium.webdriver.edge.options import Options
    
    edge_options = Options()
    edge_options.set_capability("platformName", "WIN11")
    edge_options.set_capability("browserVersion", "latest")
    edge_options.set_capability("tb:options", {
        "key": "API_KEY",
        "secret": "API_SECRET",
        "name": "Edge Headless Test",
        "headless": True
    })
    
    driver = webdriver.Remote(
        command_executor="https://hub.testingbot.com/wd/hub",
        options=edge_options
    )
    
    driver.get("https://www.google.com")
    print("Title:", driver.title)
    driver.quit()

    const { Builder } = require('selenium-webdriver');
    
    async function runHeadlessTest() {
        const driver = await new Builder()
            .forBrowser('MicrosoftEdge')
            .withCapabilities({
                'browserName': 'MicrosoftEdge',
                'browserVersion': 'latest',
                'platformName': 'WIN11',
                'tb:options': {
                    'key': 'API_KEY',
                    'secret': 'API_SECRET',
                    'name': 'Edge Headless Test',
                    'headless': true
                }
            })
            .usingServer('https://hub.testingbot.com/wd/hub')
            .build();
    
        try {
            await driver.get('https://www.google.com');
            const title = await driver.getTitle();
            console.log('Title:', title);
        } finally {
            await driver.quit();
        }
    }
    
    runHeadlessTest();

    // wdio.conf.js
    exports.config = {
        user: 'API_KEY',
        key: 'API_SECRET',
    
        capabilities: [{
            browserName: 'MicrosoftEdge',
            browserVersion: 'latest',
            platformName: 'WIN11',
            'tb:options': {
                name: 'Edge Headless Test',
                headless: true
            }
        }],
    
        services: [['testingbot']],
    
        // Your test configuration
        specs: ['./test/specs/**/*.js'],
        framework: 'mocha',
        reporters: ['spec']
    };
    
    // test/specs/example.js
    describe('Headless Edge Test', () => {
        it('should load Google', async () => {
            await browser.url('https://www.google.com');
            const title = await browser.getTitle();
            console.log('Title:', title);
        });
    });

    require 'selenium-webdriver'
    
    options = Selenium::WebDriver::Edge::Options.new
    options.platform_name = 'WIN11'
    options.browser_version = 'latest'
    
    caps = Selenium::WebDriver::Remote::Capabilities.new(
      'tb:options': {
        key: 'API_KEY',
        secret: 'API_SECRET',
        name: 'Edge Headless Test',
        headless: true
      }
    )
    
    driver = Selenium::WebDriver.for(
      :remote,
      url: 'https://hub.testingbot.com/wd/hub',
      capabilities: [options, caps]
    )
    
    driver.get('https://www.google.com')
    puts "Title: #{driver.title}"
    driver.quit

    using OpenQA.Selenium;
    using OpenQA.Selenium.Edge;
    using OpenQA.Selenium.Remote;
    
    var edgeOptions = new EdgeOptions();
    edgeOptions.PlatformName = "WIN11";
    edgeOptions.BrowserVersion = "latest";
    
    var tbOptions = new Dictionary<string, object>
    {
        ["key"] = "API_KEY",
        ["secret"] = "API_SECRET",
        ["name"] = "Edge Headless Test",
        ["headless"] = true
    };
    
    edgeOptions.AddAdditionalOption("tb:options", tbOptions);
    
    IWebDriver driver = new RemoteWebDriver(
        new Uri("https://hub.testingbot.com/wd/hub"),
        edgeOptions.ToCapabilities(),
        TimeSpan.FromSeconds(600)
    );
    
    driver.Navigate().GoToUrl("https://www.google.com");
    Console.WriteLine("Title: " + driver.Title);
    driver.Quit();

    <?php
    require_once('vendor/autoload.php');
    
    use Facebook\WebDriver\Remote\RemoteWebDriver;
    use Facebook\WebDriver\Remote\DesiredCapabilities;
    
    $capabilities = DesiredCapabilities::microsoftEdge();
    $capabilities->setCapability('browserVersion', 'latest');
    $capabilities->setCapability('platformName', 'WIN11');
    $capabilities->setCapability('tb:options', [
        'key' => 'API_KEY',
        'secret' => 'API_SECRET',
        'name' => 'Edge Headless Test',
        'headless' => true
    ]);
    
    $driver = RemoteWebDriver::create(
        'https://hub.testingbot.com/wd/hub',
        $capabilities,
        60000,
        60000
    );
    
    $driver->get('https://www.google.com');
    echo "Title: " . $driver->getTitle() . "\n";
    $driver->quit();
    ?>

Save the example below in a `headless_edge.robot` file:

    ***Settings***
    Library SeleniumLibrary
    Library TestingBot
    Library Collections
    
    Test Setup Open Headless Edge Browser
    Test Teardown Close Test Browser
    
    ***Variables***
    ${TB_KEY} API_KEY
    ${TB_SECRET} API_SECRET
    
    ***Test Cases***
    Edge Headless Test
        Go To https://www.google.com
        Title Should Be Google
    
    ***Keywords***
    Open Headless Edge Browser
        ${edge_options}= Evaluate selenium.webdriver.EdgeOptions() modules=selenium.webdriver
    
        # Set W3C capabilities
        Call Method ${edge_options} set_capability platformName WIN11
        Call Method ${edge_options} set_capability browserVersion latest
    
        # Set TestingBot options with headless enabled
        ${tb_options}= Create Dictionary name=Edge Headless Test headless=${True}
        Call Method ${edge_options} set_capability tb:options ${tb_options}
    
        Open Browser about:blank
        ... remote_url=https://${TB_KEY}:${TB_SECRET}@hub.testingbot.com/wd/hub
        ... options=${edge_options}
    
    Close Test Browser
        Report TestingBot Status
        ... ${SUITE_NAME} | ${TEST_NAME}
        ... ${TEST_STATUS}
        ... ${TB_KEY}:${TB_SECRET}
        Close All Browsers

Save the code below in a `TestingBot.py` file:

    import requests
    from robot.libraries.BuiltIn import BuiltIn
    
    def report_testingbot_status(name, status, credentials):
        selenium = BuiltIn().get_library_instance('SeleniumLibrary')
        session_id = selenium.driver.session_id
    
        payload = {'test[name]': name, 'test[success]': int(status == 'PASS')}
        key, secret = credentials.split(':')
    
        url = 'https://api.testingbot.com/v1/tests/{0}'.format(session_id)
        response = requests.put(url, data=payload, auth=(key, secret))
        assert response.status_code == 200, response.text

To run the test:

    pip install robotframework-seleniumlibrary requests
    PYTHONPATH=$PYTHONPATH:. robot headless_edge.robot

## Safari Headless Testing

**Safari does not support headless mode.** Apple has not implemented headless functionality in Safari or the SafariDriver.

If you need to run Safari tests, they will always run in headed (visible) mode. For headless testing requirements, consider using Chrome, Firefox or Edge as alternatives.

At TestingBot we run all Safari 17 and higher versions on Apple Silicon for maximum performance.

## Mobile Headless Testing

TestingBot uses Appium to run mobile tests. Appium supports running your iOS and Android tests in headless mode (no screen rendering).

To enable headless mode for mobile testing, specify the `isHeadless` capability in your test configuration.

### iOS Headless Testing
[Java](https://testingbot.com#)[Python](https://testingbot.com#)[NodeJS](https://testingbot.com#)[Ruby](https://testingbot.com#)[C#](https://testingbot.com#)

    import io.appium.java_client.ios.IOSDriver;
    import io.appium.java_client.ios.options.XCUITestOptions;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    
    public class HeadlessIOSTest {
        public static void main(String[] args) throws Exception {
            XCUITestOptions options = new XCUITestOptions();
            options.setPlatformName("iOS");
            options.setPlatformVersion("18.0");
            options.setDeviceName("iPhone 16");
            options.setBrowserName("safari");
            options.setCapability("appium:isHeadless", true);
    
            Map<String, Object> tbOptions = new HashMap<>();
            tbOptions.put("key", "API_KEY");
            tbOptions.put("secret", "API_SECRET");
            tbOptions.put("name", "iOS Headless Test");
    
            options.setCapability("tb:options", tbOptions);
    
            IOSDriver driver = new IOSDriver(
                new URL("https://hub.testingbot.com/wd/hub"),
                options
            );
    
            driver.get("https://www.google.com");
            System.out.println("Title: " + driver.getTitle());
            driver.quit();
        }
    }

    from appium import webdriver
    from appium.options.ios import XCUITestOptions
    
    options = XCUITestOptions()
    options.platform_name = "iOS"
    options.platform_version = "18.0"
    options.device_name = "iPhone 16"
    options.browser_name = "safari"
    options.set_capability("appium:isHeadless", True)
    options.set_capability("tb:options", {
        "key": "API_KEY",
        "secret": "API_SECRET",
        "name": "iOS Headless Test"
    })
    
    driver = webdriver.Remote(
        command_executor="https://hub.testingbot.com/wd/hub",
        options=options
    )
    
    driver.get("https://www.google.com")
    print("Title:", driver.title)
    driver.quit()

    const { remote } = require('webdriverio');
    
    async function runHeadlessIOSTest() {
        const driver = await remote({
            hostname: 'hub.testingbot.com',
            port: 443,
            path: '/wd/hub',
            protocol: 'https',
            capabilities: {
                'platformName': 'iOS',
                'appium:platformVersion': '18.0',
                'appium:deviceName': 'iPhone 16',
                'browserName': 'safari',
                'appium:isHeadless': true,
                'tb:options': {
                    'key': 'API_KEY',
                    'secret': 'API_SECRET',
                    'name': 'iOS Headless Test'
                }
            }
        });
    
        await driver.url('https://www.google.com');
        const title = await driver.getTitle();
        console.log('Title:', title);
        await driver.deleteSession();
    }
    
    runHeadlessIOSTest();

    require 'appium_lib'
    
    caps = {
      platformName: 'iOS',
      'appium:platformVersion': '18.0',
      'appium:deviceName': 'iPhone 16',
      browserName: 'safari',
      'appium:isHeadless': true,
      'tb:options': {
        key: 'API_KEY',
        secret: 'API_SECRET',
        name: 'iOS Headless Test'
      }
    }
    
    opts = {
      caps: caps,
      appium_lib: {
        server_url: 'https://hub.testingbot.com/wd/hub'
      }
    }
    
    driver = Appium::Driver.new(opts, true)
    driver.start_driver
    
    driver.get('https://www.google.com')
    puts "Title: #{driver.title}"
    driver.quit

    using OpenQA.Selenium.Appium;
    using OpenQA.Selenium.Appium.iOS;
    
    var options = new AppiumOptions();
    options.PlatformName = "iOS";
    options.AddAdditionalAppiumOption("appium:platformVersion", "18.0");
    options.AddAdditionalAppiumOption("appium:deviceName", "iPhone 16");
    options.AddAdditionalAppiumOption("browserName", "safari");
    options.AddAdditionalAppiumOption("appium:isHeadless", true);
    
    var tbOptions = new Dictionary<string, object>
    {
        ["key"] = "API_KEY",
        ["secret"] = "API_SECRET",
        ["name"] = "iOS Headless Test"
    };
    
    options.AddAdditionalAppiumOption("tb:options", tbOptions);
    
    var driver = new IOSDriver(
        new Uri("https://hub.testingbot.com/wd/hub"),
        options,
        TimeSpan.FromSeconds(600)
    );
    
    driver.Navigate().GoToUrl("https://www.google.com");
    Console.WriteLine("Title: " + driver.Title);
    driver.Quit();

### Android Headless Testing
[Java](https://testingbot.com#)[Python](https://testingbot.com#)[NodeJS](https://testingbot.com#)[Ruby](https://testingbot.com#)[C#](https://testingbot.com#)

    import io.appium.java_client.android.AndroidDriver;
    import io.appium.java_client.android.options.UiAutomator2Options;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    
    public class HeadlessAndroidTest {
        public static void main(String[] args) throws Exception {
            UiAutomator2Options options = new UiAutomator2Options();
            options.setPlatformName("Android");
            options.setPlatformVersion("14.0");
            options.setDeviceName("Pixel 8");
            options.setBrowserName("chrome");
            options.setCapability("appium:isHeadless", true);
    
            Map<String, Object> tbOptions = new HashMap<>();
            tbOptions.put("key", "API_KEY");
            tbOptions.put("secret", "API_SECRET");
            tbOptions.put("name", "Android Headless Test");
    
            options.setCapability("tb:options", tbOptions);
    
            AndroidDriver driver = new AndroidDriver(
                new URL("https://hub.testingbot.com/wd/hub"),
                options
            );
    
            driver.get("https://www.google.com");
            System.out.println("Title: " + driver.getTitle());
            driver.quit();
        }
    }

    from appium import webdriver
    from appium.options.android import UiAutomator2Options
    
    options = UiAutomator2Options()
    options.platform_name = "Android"
    options.platform_version = "14.0"
    options.device_name = "Pixel 8"
    options.browser_name = "chrome"
    options.set_capability("appium:isHeadless", True)
    options.set_capability("tb:options", {
        "key": "API_KEY",
        "secret": "API_SECRET",
        "name": "Android Headless Test"
    })
    
    driver = webdriver.Remote(
        command_executor="https://hub.testingbot.com/wd/hub",
        options=options
    )
    
    driver.get("https://www.google.com")
    print("Title:", driver.title)
    driver.quit()

    const { remote } = require('webdriverio');
    
    async function runHeadlessAndroidTest() {
        const driver = await remote({
            hostname: 'hub.testingbot.com',
            port: 443,
            path: '/wd/hub',
            protocol: 'https',
            capabilities: {
                'platformName': 'Android',
                'appium:platformVersion': '14.0',
                'appium:deviceName': 'Pixel 8',
                'browserName': 'chrome',
                'appium:isHeadless': true,
                'tb:options': {
                    'key': 'API_KEY',
                    'secret': 'API_SECRET',
                    'name': 'Android Headless Test'
                }
            }
        });
    
        await driver.url('https://www.google.com');
        const title = await driver.getTitle();
        console.log('Title:', title);
        await driver.deleteSession();
    }
    
    runHeadlessAndroidTest();

    require 'appium_lib'
    
    caps = {
      platformName: 'Android',
      'appium:platformVersion': '14.0',
      'appium:deviceName': 'Pixel 8',
      browserName: 'chrome',
      'appium:isHeadless': true,
      'tb:options': {
        key: 'API_KEY',
        secret: 'API_SECRET',
        name: 'Android Headless Test'
      }
    }
    
    opts = {
      caps: caps,
      appium_lib: {
        server_url: 'https://hub.testingbot.com/wd/hub'
      }
    }
    
    driver = Appium::Driver.new(opts, true)
    driver.start_driver
    
    driver.get('https://www.google.com')
    puts "Title: #{driver.title}"
    driver.quit

    using OpenQA.Selenium.Appium;
    using OpenQA.Selenium.Appium.Android;
    
    var options = new AppiumOptions();
    options.PlatformName = "Android";
    options.AddAdditionalAppiumOption("appium:platformVersion", "14.0");
    options.AddAdditionalAppiumOption("appium:deviceName", "Pixel 8");
    options.AddAdditionalAppiumOption("browserName", "chrome");
    options.AddAdditionalAppiumOption("appium:isHeadless", true);
    
    var tbOptions = new Dictionary<string, object>
    {
        ["key"] = "API_KEY",
        ["secret"] = "API_SECRET",
        ["name"] = "Android Headless Test"
    };
    
    options.AddAdditionalAppiumOption("tb:options", tbOptions);
    
    var driver = new AndroidDriver(
        new Uri("https://hub.testingbot.com/wd/hub"),
        options,
        TimeSpan.FromSeconds(600)
    );
    
    driver.Navigate().GoToUrl("https://www.google.com");
    Console.WriteLine("Title: " + driver.Title);
    driver.Quit();

## Benefits of Headless Testing

- **Faster Test Execution:** Without rendering the UI, tests start and complete more quickly. 
- **Lower Resource Usage:** Headless browsers consume less memory and CPU. 
- **Ideal for CI/CD:** Perfect for automated pipelines where visual output is not needed. 
- **Screenshots Supported:** You can still capture screenshots during headless tests. 

## Limitations

- **No Video Recording:** Video recording is not available during headless tests. 
- **Debugging:** Debugging can be more challenging without seeing the browser UI. 

For debugging purposes, we recommend switching to headed mode temporarily to visually inspect the browser during test execution.

Was this page helpful? Yes No 

## Looking for More Help?

Have questions or need more information?   
 You can reach us via the following channels:

- [Email us](https://testingbot.com/contact/new)
- [Join our Slack Channel](https://join.slack.com/t/testingb0t/shared_invite/zt-3bcw9xch-jk19~6XPs_xBrsAgAedkCw)
