How to Run Headless Browser in Python and Selenium
Tags: python, programming, webdev, beginners
Published: 2023-11-16 21:18:24

Traditional browsers with GUIs consume a lot of system resources when at scale. Also, it requires a visible window to render web pages, which can slow down test execution and limit scalability. Headless browsers eliminate the need for a GUI by running in the background without a visible interface. This solves the problem of resource-intensive testing, allowing for more efficient test execution and improved scalability.

Also, another important limitation of [test automation](https://www.lambdatest.com/learning-hub/automation-testing?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=learning_hub) is running tests on different platforms and environments. With headless browsers, tests can be executed on various platforms, which makes them suitable for running without a screen. This offers the advantage of [faster test execution](https://www.lambdatest.com/fast-test-execution?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage) and reduced resource consumption compared to traditional browsers.

It ensures consistent test execution across different environments, eliminating the need to set up and maintain multiple physical or virtual machines. Headless browsers provide a platform-agnostic solution that simplifies testing and increases test coverage.

This blog provides a comprehensive guide on leveraging headless browsers in Python for [Selenium automation](https://www.lambdatest.com/selenium-automation?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage) and web development tasks. It starts by discussing the benefits and practical applications of headless browsers.

Afterward, it delves into implementing [headless browsing testing](https://www.lambdatest.com/learning-hub/headless-browser-testing?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=learning_hub) with Selenium in Python. The blog explains how to perform [parallel testing](https://www.lambdatest.com/blog/what-is-parallel-testing-and-why-to-adopt-it/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog) with headless browsers and uses a cloud-based testing platform to illustrate these concepts.
>  **Minimize the file size of your CSS files for faster loading web pages with our free online [CSS Minify](https://www.lambdatest.com/free-online-tools/css-minify?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) tool. Easy and efficient minification in just a few clicks.**

## Overview of Headless Browsers

Headless browsers, as the name suggests, are web browsers that operate without a visible interface. Unlike traditional browsers, which render web pages and display them in a graphical user interface, headless browsers perform the same operations behind the scenes without any visual representation.

They are particularly useful for tasks requiring web page interaction, data extraction, [web scraping](https://www.lambdatest.com/blog/web-scraping-with-python/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog), [automated testing](https://www.lambdatest.com/learning-hub/automation-testing?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=learning_hub), or any other scenario where a user interface is unnecessary. By running in a headless mode, these browsers can operate more efficiently, consume fewer resources, and provide enhanced scalability.

Consider a situation where we run a script that opens 4 Chrome browser instances and accesses a web page. Running this in Chrome consumes 78% of the CPU. In headless, Chrome consumes 44% of the CPU.

**Chrome**

![](https://cdn-images-1.medium.com/max/2000/0*9_cp08SdEWH3oksu.jpg)

**Chrome Headless**

![](https://cdn-images-1.medium.com/max/2000/0*Rd-GsgZ4eBY6Kiap.jpg)

We know this may vary from machine to machine, but we want to present this in the blog to show a decrease of 43% in CPU consumption when using headless browsers.

Several popular headless browsers are available, each with its own features and capabilities. Some of the most notable ones include:

**Headless Chrome**

[Headless Chrome](https://www.lambdatest.com/blog/headless-chrome/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog) is the headless mode of the Chrome browser. It provides the same capabilities as the regular Chrome browser but without a visible interface. Headless Chrome is widely used for automated testing, web scraping, and other tasks that require [browser automation](https://www.lambdatest.com/learning-hub/browser-automation?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=learning_hub).

**Headless Firefox**

Headless Firefox is the headless mode of the Firefox browser. It offers similar functionalities to Headless Chrome and is known for its compatibility with web standards and support for complex web applications.

**Puppeteer**

[Puppeteer](https://www.lambdatest.com/puppeteer?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage) is a Node.js library developed by Google that provides a high-level API for controlling headless Chrome or Chromium browsers. It offers powerful capabilities for automating browser tasks, generating screenshots and PDFs, and executing JavaScript code within web pages.

**PhantomJS**

PhantomJS is a headless browser built using the WebKit engine. It provides a JavaScript API for page manipulation and supports various web standards. However, it is worth noting that PhantomJS has been deprecated and is no longer actively maintained.

By leveraging headless browsers with the Python library in Selenium, developers and testers can automate browser actions, interact with web pages, extract data, and perform a wide range of tasks efficiently and effectively.

In the upcoming sections of this blog on headless browsers in Python, we will explore the advantages and disadvantages of headless browsers, focusing on the Headless Chrome and Headless Firefox browsers, dive into the details of running headless browsers in Python with Selenium, and explore advanced techniques for handling various web interactions.
>  **Minify your XML code with our efficient and reliable online free tool for better website performance. Get faster page load times and better results today with [XML Minify](https://www.lambdatest.com/free-online-tools/xml-minify?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools).**

## Advantages and Shortcomings of Headless Browsers

Headless browsers offer several advantages that make them a valuable tool for various web-related tasks. While headless browsers provide numerous advantages, some disadvantages should be considered when deciding whether to use them.

Let’s explore some key advantages and disadvantages of using headless browsers.

## Advantages

**Improved performance and resource efficiency**

Headless browsers operate without a visible GUI, reducing the overhead of visually rendering web pages. This translates to improved performance and resource efficiency, as they consume fewer system resources and require less memory.

Test automation can run faster with optimized resource utilization, resulting in faster and more efficient processes.

**Scalability and parallel execution**

Headless browsers enable parallel execution of tests and tasks, making them highly scalable. Multiple tests or tasks can run concurrently, saving time and increasing productivity.

This parallel execution capability is particularly useful in scenarios where there is a need to process a large volume of data or execute tests across multiple environments. It allows for faster feedback on the quality of the software being tested and improves the efficiency of the test automation process.

**Server-side rendering and SEO optimization**

Headless browsers can be leveraged for server-side rendering, which involves generating fully rendered HTML pages on the server before sending them to the client. This approach improves page load times and enhances search engine optimization (SEO), as search engine crawlers can easily index the pre-rendered content.

Headless browsers enable websites to provide pre-rendered content to users and search engine crawlers, resulting in better performance and improved visibility in search engine rankings.
>  **Tired of hard-to-read SQL code? Use our fast and reliable [SQL Beautifier](https://www.lambdatest.com/free-online-tools/sql-beautifier?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) tool to format and beautify your SQL code, making it more structured and easy to read.**

**Compatibility across multiple platforms**

Headless browsers are compatible with various operating systems, making them ideal for cross-platform testing and automation. They can be used on platforms like Windows, Linux, and macOS without platform-specific configurations. This compatibility ensures consistent [test execution](https://www.lambdatest.com/learning-hub/test-execution?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=learning_hub) and automation across different environments, saving time and effort in maintaining separate setups for each platform.

The compatibility may depend on the Chrome/Firefox version for Chrome and Firefox.

## Shortcomings

**Lack of visual rendering for debugging and testing**

One major drawback of headless browsers is the absence of a graphical interface, making debugging and testing more challenging. Unlike traditional browsers, which display web pages visually, headless browsers do not visually represent the page during test execution.

This makes it difficult to identify visual issues or inspect elements visually. A good approach to address the limitation of the absence of a graphical interface in headless browsers is to leverage the browser’s built-in capabilities for logging and capturing console output. Headless browsers typically provide methods to log messages, errors, and warnings to the console, which can be invaluable for debugging purposes.

**Increased complexity in handling JavaScript-based interactions**

Many modern websites rely heavily on JavaScript to deliver dynamic content and interactivity. Headless browsers need to handle JavaScript execution to ensure the proper functioning of web applications during test automation or web scraping.

However, there may be specific differences or limitations in JavaScript handling, like incomplete DOM support, lack of visual rendering, differences in JavaScript engines, and limited support for browser-specific APIs compared to their GUI counterparts.

This could require additional attention and workarounds for JavaScript-dependent scenarios, like mocking or stubbing, custom JavaScript code, headless browser extensions, network interception and modification, and alternative validation techniques.

Developers and testers need to be aware of these complexities and ensure that their scripts account for any discrepancies, like JavaScript execution errors and timing and synchronization issues.

**Limited support for certain browser-specific features**

Headless browsers may have limited support for browser-specific features or behaviors, like [CSS animations](https://lambdatest.com/blog/css-animations-tutorial/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog) and transitions, JavaScript pop-ups, and video/audio playback. This can pose challenges when testing or automation scenarios that rely on these specific features. It is crucial to carefully consider the target browser’s requirements and limitations before opting for a headless approach.

**Learning curve and setup requirements**

Using headless browsers may require a learning curve, particularly for individuals accustomed to working with traditional browsers. Developers and testers need to familiarize themselves with the unique features, APIs, and limitations of the chosen headless browser.

For example, Chrome and Chrome Headless browsers have some differences, like:

* **Visual rendering:** The Chrome Headless browser does not render web pages. This means that elements like images, CSS styling, and animations are not visually rendered in headless mode.

* **Browser window size:** There is no window to resize or maximize in headless mode since there is no visible interface.

* **User interactions:** In headless mode, direct user interactions are not possible since there is no graphical interface.

* **Debugging capabilities:** In headless mode, some debugging capabilities may differ or be more limited compared to the regular browser’s extensive debugging features.

* **Headless-specific APIs:** The Chrome Headless browser may provide additional APIs or command-line options that are specific to headless mode.

However, once the initial learning and setup phases are complete, the benefits of using headless browsers can outweigh these initial challenges.

It is important to weigh these advantages and shortcomings to determine whether headless browsers fit a specific project or use case. While they offer significant benefits in terms of performance, scalability, and compatibility, their limitations should be considered and addressed to ensure effective and efficient test automation and web-related tasks.
>  **Struggling with messy Lua scripts? Our [Lua Beautifier](https://www.lambdatest.com/free-online-tools/lua-beautifier?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) tool provides clean and structured formatting. Beautify your code and Improve readability today!**

## Running Headless Browser in Python with Selenium

Running headless browsers with Python in Selenium opens up a world of possibilities for automating web interactions and performing tasks without a visible browser window.

This section will explore how to initialize a headless browser and navigate web pages using Selenium in Python. We’ll cover creating a WebDriver instance, configuring the headless mode, loading webpages, interacting with elements on the page, and extracting data from the page.

## Prerequisites: Setup Process

To start our coding, we need to proceed with the following steps to prepare the environment.

**Step 1: Download and Install Python**

If not already installed, begin by installing Python from the official website.

**Step 2: Install Selenium and pytest libraries**

Once Python is installed, use the Python package manager, pip, to install Selenium and pytest. *pip* is a package management system written in Python used to install/manage packages and libraries.

If you do not have *pip* installed on your machine, you should follow the below steps for Windows:

 1. Download the get-*pip.py* script by visiting the official pip installation page.

 2. Save the get-*pip.py* file to your computer.

 3. Open a command prompt and navigate to the directory where you saved the get-*pip.py* file.

 4. Run the following command:

    python get-pip.py

Then you can check the installation using the below command:

    pip — version

![](https://cdn-images-1.medium.com/max/2224/0*u_X_3U14ZU2WiDgk.png)

Now, you can install Selenium and pytest by running the following command:

    pip install -r requirements.txt

requirements.txt contains the dependencies that we want to install.

![](https://cdn-images-1.medium.com/max/2952/0*jvDe9lvmDeEqOZ5h.png)

After running it, you can see the output below.

![](https://cdn-images-1.medium.com/max/2372/0*JlU_33TXMgHkEHcc.png)

**Step 3: Download and Install Visual Studio Code**

Visual Studio Code (VSC) will be the IDE we will use in this blog. However, you are free to use your preferred IDE.

**Step 4: Configure pytest in Visual Studio Code**

To finish the configuration, we need to instruct Visual Studio Code that pytest will be our [test runner](https://www.lambdatest.com/learning-hub/test-runner?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=learning_hub); you can do this by following the below instructions:

 1. Create a folder for your project (in our example python-headless-browser).

 2. Open the project folder in Visual Studio Code.

 3. Open the command palette (menu View > Command Palette), and type “Configure Tests.”

 4. Select pytest as the test framework.

 5. Select the *root directory* option.

Now, we are ready to start!

## Initializing a Headless Browser

To run the headless browser with Python, we need to initialize a headless browser instance. This involves creating a WebDriver object and configuring it to run in headless mode.

### Chrome

    chrome_options.add_argument(‘ — headless’)

### Firefox

    firefox_options.add_argument(‘ — headless’)

## Navigating Web Pages

Once we have a headless browser instance, we can navigate web pages, interact with elements, and extract data from the page. Let’s explore how to perform these tasks using [Selenium with Python](https://www.lambdatest.com/blog/getting-started-with-selenium-python/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog).

**Loading a Webpage**

To load a webpage in the headless browser, we use the *get()* method of the WebDriver object. Here’s an example:

    # Load a webpage
    driver.get("https://www.lambdatest.com/selenium-playground/simple-form-demo")

The above code uses the get() method to load the webpage with the URL “*https://www.lambdatest.com/selenium-playground/simple-form-demo.*” The headless browser will retrieve and render the page, allowing us to interact with its elements.
>  **Struggling with messy [PHP Beautifier](https://www.lambdatest.com/free-online-tools/php-beautifier?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) & Formatter Online scripts? Our PHP Formatter & Beautifier Online tool provides clean and structured formatting. Beautify your code and Improve readability today!**

**Interacting with Elements on the Page**

With the headless browser loaded with a web page, we can interact with various elements on the page, such as typing in a field, clicking buttons, or extracting data. [Selenium](https://www.lambdatest.com/selenium?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage) provides a wide range of methods and functions to perform these actions. Let’s see some examples:

      # Find an input element by its ID and enter text
        input_element = driver.find_element(By.ID, "user-message")
        input_element.send_keys("This is a headless browser text!")
        # Find an element by its ID and click on it
        element = driver.find_element(By.ID, "showInput")
        element.click()

In the above code snippets, we use the [*find_element() *method](https://www.lambdatest.com/blog/findelement-and-findelements-in-selenium/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog) to locate elements on the page. These methods allow us to find elements using different strategies, such as by ID, name, class name, [CSS Selector](https://www.lambdatest.com/blog/css-selectors/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog), and more. Once we have a reference to an element, we can interact with it using methods like *click()* or [*send_keys() *in Selenium](https://www.lambdatest.com/blog/how-to-use-selenium-sendkeys/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog).

**Extracting Data from the Page**

Extracting data from a web page is common in web scraping and test automation. Selenium provides several methods to locate and extract data from elements on the page. Let’s take a look at this example:

    # Find an element by its ID and extract its text
        element = driver.find_element(By.ID, "message")
        print(element.text)

In the code snippets above, we use the *find_element()* method to locate elements on the page. We then use methods like text to extract the desired data from the elements.

You can run the entire code using the below command:

    pytest test_headless-1.py

![](https://cdn-images-1.medium.com/max/2052/0*sV-P3lPXzNKCRQfE.png)

## Test Automation with Headless Browser in Python

Now, let’s automate a more complex test scenario. We want to automate the filling in the below register form of the [LambdaTest eCommerce Playground](https://ecommerce-playground.lambdatest.io/index.php?route=account/register?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage) website. This website provides a safe environment for developers to test their code and applications.

![](https://cdn-images-1.medium.com/max/2000/0*M36DdweL5S4w2i6E.png)

When filling out this form, we will see the screen below. Pay attention to the message displayed on the Chrome tab. This is the message we will assert at the end of our [test case](https://www.lambdatest.com/learning-hub/test-case?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=learning_hub).

![](https://cdn-images-1.medium.com/max/3038/0*ty0c5hk-uX_-uPbv.png)

 1. Open the Register Account form in the [LambdaTest eCommerce Playground](https://ecommerce-playground.lambdatest.io/index.php?route=account/register?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage).

 2. Fill in the personal details.

 3. Fill in the password.

 4. Subscribe to the newsletter.

 5. Accept the terms and conditions.

 6. Click the Continue button.

 7. Check that a success message is shown to the user in the browser tab.

### Implementation

    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver.common.by import By
    
    
    def test_register_account_form():
        # Create an instance of ChromeOptions
        chrome_options = Options()
        # Configure ChromeOptions to run in headless mode
        chrome_options.add_argument('--headless')
    
    
        # Initialize the WebDriver with the configured ChromeOptions
        driver = webdriver.Chrome(options=chrome_options)
    
    
        driver.get("https://ecommerce-playground.lambdatest.io/index.php?route=account/register")
    
    
        first_name = driver.find_element(By.ID, "input-firstname")
        first_name.send_keys("FirstName")
    
    
        last_name = driver.find_element(By.ID, "input-lastname")
        last_name.send_keys("LastName")
    
    
        email = driver.find_element(By.ID, "input-email")
        email.send_keys("blogtest+222@example.com")
    
    
        telephone = driver.find_element(By.ID, "input-telephone")
        telephone.send_keys("+351999888777")
    
    
        password = driver.find_element(By.ID, "input-password")
        password.send_keys("123456")
    
    
        password_confirm = driver.find_element(By.ID, "input-confirm")
        password_confirm.send_keys("123456")
    
    
        newsletter = driver.find_element(By.XPATH, value="//label[@for='input-newsletter-yes']")
        newsletter.click()
    
    
        terms = driver.find_element(By.XPATH, value="//label[@for='input-agree']")
        terms.click()
    
    
        continue_button = driver.find_element(By.XPATH, value="//input[@value='Continue']")
        continue_button.click()
    
    
        assert driver.title == "Your Account Has Been Created!"

### Code Walkthrough

First, let’s set up the necessary imports for the code to work correctly. We import the *webdriver* module from the Selenium library and specific submodules like options from *selenium.webdriver.chrome.options* and *By* from *selenium.webdriver.common.by*. These modules provide us with the necessary tools to configure the Chrome browser, locate elements on the web page, and interact with them.

![](https://cdn-images-1.medium.com/max/2700/0*0krs_XivXmNh_uL2.png)

Next, we create a function called *test_register_account_form*, where inside it, we create an instance of *ChromeOptions* and assign it to the variable *chrome_options*. In this case, we want to run the browser in headless mode without a visible GUI. We achieve this by adding the — *headless* argument to *chrome_options*.

With the *ChromeOptions* configured, we initialize the WebDriver by creating an instance of *webdriver.Chrome* and passing in the options parameter set to *chrome_options*. This step creates a new Chrome browser instance with the specified options, including running in headless mode.

![](https://cdn-images-1.medium.com/max/3132/0*2j9NVl44cEq6ZU6o.png)

Now, we can start interacting with the web page. The *driver.get()* method is used to navigate to a specific URL.

![](https://cdn-images-1.medium.com/max/3200/0*MK_T1-9qW0Nwa4i2.png)

To fill out the registration form, we locate each form field element on the web page using the *driver.find_element()* method. We pass in the method *By.ID* as the locator strategy and the corresponding *ID* of the form field element as the value.
>  **Struggling with messy [Python Beautifier](https://www.lambdatest.com/free-online-tools/python-beautifier?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) & Formatter Online scripts? Our Python Formatter & Beautifier Online tool provides clean and structured formatting. Beautify your code and Improve readability today!**

For example, *first_name* corresponds to the input field with the ID *input-firstname*.

![](https://cdn-images-1.medium.com/max/3200/0*zckh1ZCVcLGLmcBl.png)

Once we have located the element, we use the *send_keys()* method to simulate typing in the desired input. In this case, we enter “*FirstName*” as the first name.

![](https://cdn-images-1.medium.com/max/2896/0*P0UjsQ4swavQuTa_.png)

We repeat this process for other form fields such as last name, email, telephone, password, and password confirmation. Additionally, we interact with checkboxes for the newsletter subscription and terms agreement. We locate these elements using the *By.XPATH* locator strategy and provide the corresponding XPath value. Finally, we use the *click()* method to simulate a mouse click on the checkboxes.

![](https://cdn-images-1.medium.com/max/3200/0*f0oojwxRYjOCyOJZ.png)

After filling out the form, we locate the Continue button using the *By.XPATH* locator and click on it to submit the form.

![](https://cdn-images-1.medium.com/max/3200/0*ygw7cPD_FygQQiaH.png)

Lastly, we assert the resulting page title to ensure a successful registration. In this example, we assert that the page title is “*Your Account Has Been Created!*“. If the assertion fails, an exception will be raised, indicating that the registration process did not go as expected.

![](https://cdn-images-1.medium.com/max/2776/0*74S3mcso28wecVCE.png)

You can run the above code using the below command:

    pytest test_headless-2.py

![](https://cdn-images-1.medium.com/max/2044/0*fA7htO6DMgUvnHO7.png)

By leveraging the capabilities of headless browsers with Python and Selenium, we can automate web interactions, perform tests, and extract data from web pages effectively and efficiently.

In the next section of this blog on Python headless browsers, we will delve into parallel testing using a headless browser, which further enhances the capabilities and efficiency of our [automation testing](https://www.lambdatest.com/automation-testing?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage) process.
>  **Make the conversion from [YAML to JSON](https://www.lambdatest.com/free-online-tools/yaml-to-json?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) quick and easy with our free online converter YAML to JSON converter tool. No signup or installation required. Try it now!**

## Parallel Testing Using Headless Browser in Python

This blog section on Python headless browsers will explore how to perform parallel testing with Selenium Python using a headless browser. Parallel testing allows us to run multiple test cases simultaneously, reducing the overall testing time and increasing efficiency.

We will discuss the steps to set up the [testing environment](https://www.lambdatest.com/blog/what-is-test-environment/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog), including installing Python and Selenium, configuring the [Selenium WebDriver](https://www.lambdatest.com/learning-hub/webdriver?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=learning_hub), and installing the necessary dependencies for parallel testing. Then, we can implement an example using a cloud-based Selenium grid.

The demonstration will be done on a cloud-based grid like LambdaTest, an AI-powered test orchestration and execution platform that helps developers and testers to perform [Python automation testing](https://www.lambdatest.com/python-automation-testing?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage) of their websites or web applications on over 3000+ real browsers and operating system combinations.

While performing testing on LambdaTest, you can run your automated tests in parallel across multiple browsers and OS combinations, reducing the overall test execution cycles.
{% youtube SqQ8SugRDos %}
Subscribe to the [LambdaTest YouTube Channel](https://www.youtube.com/c/LambdaTest?sub_confirmation=1?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=youtube) for more videos around headless testing with Selenium JavaScript and Cypress.

To perform [Selenium Python testing](https://www.lambdatest.com/selenium-python-testing?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage) on the LambdaTest cloud grid, you need to use the capabilities to configure the environment where the test will run.

In this Python headless browser tutorial, we will run the tests with the following characteristics:

**Environment 1**

* **Browser:** Chrome

* **OS:** Windows 11

**Environment 2**

* **Browser:** Firefox

* **OS:** macOS Ventura

We are going to execute the same test scenario automated in the previous section, which is again exposed below:
>  **Simplify the process of converting [JSON to HTML](https://www.lambdatest.com/free-online-tools/json-to-html?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) with our efficient online JSON to HTML converter to convert your JSON data to HTML code quickly and easily.**

## Test Scenario

 1. Open the Register Account form in the [LambdaTest eCommerce Playground](https://ecommerce-playground.lambdatest.io/index.php?route=account/register?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage).

 2. Fill in the personal details.

 3. Fill in the password.

 4. Subscribe to the newsletter.

 5. Accept the terms and conditions.

 6. Click the Continue button.

 7. Check that a success message is shown to the user in the browser tab.

## Setting up the Environment

Before diving into parallel testing, we need to ensure that our testing environment is properly set up. Here are the essential steps that we need. They were previously explained in the previous section:

 1. Install Python.

 2. Install Selenium WebDriver.

 3. Install pytest.

 4. Install your IDE, in our case, Visual Studio Code.

 5. Configure pytest in Visual Studio Code.

You need also to prepare the LambdaTest capabilities code to be inserted in our [test script](https://www.lambdatest.com/learning-hub/test-scripts?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=youtube).

You can generate the capabilities code from the [LambdaTest Capabilities Generator](https://www.lambdatest.com/capabilities-generator/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage).

Then, you should get the “*Username*” and “*Access Token*” from your account in your [LambdaTest Profile Section](https://accounts.lambdatest.com/detail/profile?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage) and set them as environment variables.

With the environment set up, we can proceed to implement parallel testing using headless browsers.

## Implementation of Parallel Testing on LambdaTest

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    import pytest
    import os
    import random
    
    
    @pytest.fixture(params=["chrome-Windows11", "firefox-macOSVentura"],scope="class")
    def driver(request):
        username = os.getenv("LT_USERNAME")
        accessToken = os.getenv("LT_ACCESS_KEY")
        gridUrl = "hub.lambdatest.com/wd/hub"
    
    
        if request.param == "chrome-Windows11":
            web_driver = webdriver.ChromeOptions()
            platform = "Windows 11"
        if request.param == "firefox-macOSVentura":
            web_driver = webdriver.FirefoxOptions()
            platform = "MacOS Ventura"
    
    
        lt_options = {
            "user": username,
            "accessKey": accessToken,
            "build": "your build",
            "name": "your test",
            "platformName": platform,
            "w3c": True,
            "browserName": "Chrome",
            "browserVersion": "latest",
            "selenium_version": "4.8.0",
            "headless": True
        }
        options = web_driver
        options.set_capability('LT:Options', lt_options)
    
    
        url = "https://"+username+":"+accessToken+"@"+gridUrl
       
        driver = webdriver.Remote(
            command_executor=url,
            options=options
        )
    
    
        yield driver
       
        driver.quit
    
    
    def test_register_account_form(driver):
        driver.get("https://ecommerce-playground.lambdatest.io/index.php?route=account/register")
    
    
        first_name = driver.find_element(By.ID, "input-firstname")
        first_name.send_keys("FirstName")
    
    
        last_name = driver.find_element(By.ID, "input-lastname")
        last_name.send_keys("LastName")
    
    
        random_number = str(random.randrange(1, 5000, 1))
    
    
        email = driver.find_element(By.ID, "input-email")
        email.send_keys("blogtest+" + random_number +"@example.com")
    
    
        telephone = driver.find_element(By.ID, "input-telephone")
        telephone.send_keys("+351999888777")
    
    
        password = driver.find_element(By.ID, "input-password")
        password.send_keys("123456")
    
    
        password_confirm = driver.find_element(By.ID, "input-confirm")
        password_confirm.send_keys("123456")
    
    
        newsletter = driver.find_element(By.XPATH, value="//label[@for='input-newsletter-yes']")
        newsletter.click()
    
    
        terms = driver.find_element(By.XPATH, value="//label[@for='input-agree']")
        terms.click()
    
    
        continue_button = driver.find_element(By.XPATH, value="//input[@value='Continue']")
        continue_button.click()
    
    
        assert driver.title == "Your Account Has Been Created!"

## Code Walkthrough

We import the necessary modules: webdriver, *By, pytest, os,* and *random*. These modules provide the required functionality for configuring the WebDriver, locating web elements, performing assertions, supporting the test case, and managing [test fixtures in pytest](https://www.lambdatest.com/blog/end-to-end-tutorial-for-pytest-fixtures-with-examples/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog).

![](https://cdn-images-1.medium.com/max/2304/0*H0j_ddERcgw2U018.png)

Next, we define a pytest fixture named driver. The fixture is responsible for setting up the WebDriver instance that will be used for the tests. It takes a parameter called request, which allows us to access the test parameterization. To understand parameterization better, look at this blog on [Parameterization in pytest](https://www.lambdatest.com/blog/parameterization-in-pytest-with-selenium/?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=blog).

In this fixture, we want to run the tests in the environments mentioned before: Windows 11 + Chrome and macOS Ventura + Firefox.

![](https://cdn-images-1.medium.com/max/3200/0*NNtBwlx1I9pNdTV7.png)

Inside the fixture, we retrieve the necessary environment variables, such as the LambdaTest *username, accessToken*, and the *gridUrl*. These credentials are used to authenticate and connect to the [LambdaTest online Selenium grid](https://www.lambdatest.com/selenium-grid-online?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=webpage).

![](https://cdn-images-1.medium.com/max/2184/0*kt7LUORdva9u6Gk2.png)
>  **Simplify the process of converting [CSV to HTML](https://www.lambdatest.com/free-online-tools/csv-to-html?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) with our fast and accurate online CSV to HTML converter tool to convert your CSV files to HTML format. Try it now for free!**

We then use the test parameter specified in the request.param to determine the desired browser and platform for the test. In this example, we have two test parameter options: *chrome-Windows11* and *firefox-macOSVentura*. Based on the parameter value, we create an instance of *webdriver.ChromeOptions* or *webdriver.FirefoxOptions* accordingly. We also set the platform variable to represent the chosen platform.

![](https://cdn-images-1.medium.com/max/2304/0*OgfRP4sY4WCGsGmm.png)

The next step is configuring the LambdaTest options, such as the username, access key, build name, test name, platform name, browser name, browser version, Selenium version, and headless mode. These options are stored in a dictionary named *lt_options*.

We then assign the web_driver instance to the options variable and set the capability *LT:Options* to the *lt_options* dictionary. This capability ensures that the LambdaTest specific options are correctly passed to the WebDriver.

The *headless:* True parameter in the *lt_options* dictionary indicates that the tests will be executed in headless mode, meaning there will be no visible browser window during the test execution. This allows for testing using [Selenium pytest](https://www.lambdatest.com/learning-hub/selenium-pytest-tutorial?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=youtube) without needing a graphical interface.

![](https://cdn-images-1.medium.com/max/2528/0*ZbdSjIyYzGFkm1qt.png)

We construct the LambdaTest URL by combining the *username, accessToken*, and *gridUrl*. This URL will be used as the *command_executor* when creating the *webdriver.Remote* instance.

![](https://cdn-images-1.medium.com/max/2700/0*DHnvAef_p30_FBNL.png)

Finally, we create the WebDriver instance by calling *webdriver.Remote()* with the constructed URL and the options parameter. This sets up the connection to the LambdaTest Selenium Grid and initializes the WebDriver.

![](https://cdn-images-1.medium.com/max/2000/0*y1V4fdngCicfKdeD.png)

The driver fixture is then yielded, allowing the test function to utilize the WebDriver. After the test is completed, the *driver.quit* method is called to gracefully close the WebDriver session.

![](https://cdn-images-1.medium.com/max/2000/0*Am-Od5An4cyZH_rp.png)

The *test_register_account_form* function is a test case that demonstrates how to interact with a web page using the WebDriver. The test opens a registration form, fills out the form fields with sample data, performs various actions, and submits the form. The code is almost identical to the one presented and explained in the previous section.

We just did one modification. Since we are running the tests multiple times in the same execution, we need to create a random way to have a different email in each execution. If you try to use the same email, the application under test will not allow it. This is the change done in the previous code.

![](https://cdn-images-1.medium.com/max/2976/0*gwQk6ueLOOockE_G.png)

First, the line *random_number = str(random.randrange(1, 5000, 1))* generates a random integer number between 1 and 5000. The *random.randrange()* function is used for this purpose, with the start value (inclusive) and the end value (exclusive). The third argument, 1, is the step size, indicating that the random number will be incremented by 1 each time.

Next, we locate the email input field as we did before. Once the element is located, we use the *send_keys()* method to enter the generated email address. The email address is constructed by concatenating the string “*blogtest+*” with the generated random number and the domain. This ensures that a unique email address is used each time the test runs.

When running the above code, we have the below results:

![](https://cdn-images-1.medium.com/max/2214/0*iL2CyE5r6Tgq88C0.png)
>  **Convert your XML data to TSV format effortlessly using our powerful and intuitive [XML to TSV](https://www.lambdatest.com/free-online-tools/xml-to-tsv?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) Converter tool. Our converter is fast, accurate, and requires no technical expertise.**

Also, we can see in the LambdaTest Web Automation Dashboard that for this test, we had two executions, exactly what we expected.

![](https://cdn-images-1.medium.com/max/2572/0*MCNdsfoH3mAeZDn-.png)

With the implementation of parallel testing using a headless browser on LambdaTest, you can significantly reduce the overall testing time while ensuring thorough [test coverage](https://www.lambdatest.com/learning-hub/test-coverage?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=youtube) across multiple browsers and platforms. Leveraging the power of headless browsers and the scalability of parallel testing, you can enhance your test automation workflow and efficiently deliver high-quality software.

## Conclusion

In this Python headless browser tutorial, we have explored the world of headless browsers and their significance in test automation using Selenium in Python.

We began by providing an overview of headless browsers, understanding them as browsers without a graphical user interface. Headless browsers allow us to perform web interactions, automate tasks, and extract data from web pages without a visible browser window. This makes them highly suitable for test automation, where we can execute tests efficiently and effectively.

Next, we delved into the advantages of using headless browsers. We discussed how headless browsers improve performance and resource efficiency by eliminating the need for rendering and graphical operations.

With headless browsers, we can achieve scalability and parallel execution, enabling us to run multiple tests simultaneously and reduce the overall testing time. Additionally, headless browsers offer server-side rendering and SEO optimization, ensuring that our web applications are search engine-friendly and deliver optimal performance. Moreover, headless browsers provide compatibility across multiple platforms, allowing us to execute tests on different operating systems without any compatibility issues.
>  **Don’t waste time manually converting ASCII text to binary code. Use our free online [ASCII to binary](https://www.lambdatest.com/free-online-tools/ascii-to-binary?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) converter to convert any ASCII text to binary code instantly!**

## Frequently Asked Questions (FAQs)

### How do I run a headless browser in Python?

To run a headless browser in Python, you can use libraries like Selenium or Puppeteer. They allow you to automate web interactions without a visible browser window.

### What is the fastest headless browser?

The fastest headless browser can vary depending on your specific use case and requirements. Popular options include Headless Chrome, Headless Firefox, and Chromium. Performance may vary depending on the task you’re performing.

### Is Scrapy a headless browser?

Scrapy is not a headless browser but a web scraping framework. It can be used with headless browsers like Selenium to scrape data from websites effectively.

### Which browser is a headless browser?

A headless browser is a web browser without a graphical user interface (GUI) that can be controlled programmatically. Common headless browsers include Headless Chrome, Headless Firefox, and Chromium, which are used for tasks like web scraping and automated testing.
>  **Need to convert Gray code to binary? Our online [Gray to Binary](https://www.lambdatest.com/free-online-tools/gray-to-binary?utm_source=devto&utm_medium=organic&utm_campaign=nov_17&utm_term=bh&utm_content=free_online_tools) Code Converter to convert Gray code to binary quickly and easily in seconds. Try it now!**