Selenium Grid for Cross-Browser Testing: Architecture & Setup Guide

Selenium Grid for Cross-Browser Testing: Architecture & Setup Guide

Selenium Grid lets you run tests across multiple browsers and machines in parallel by routing test commands from a central hub to registered browser nodes. Grid 4, the current version, supports standalone mode, hub/node mode, and fully distributed mode. Docker Selenium makes spinning up a cross-browser grid trivial. This guide covers architecture, setup, scaling, and when Grid is the right choice.

Key Takeaways

  • Selenium Grid 4 supports three deployment modes: standalone, hub/node, and fully distributed
  • Docker Selenium provides pre-built images for Chrome, Firefox, and Edge nodes — no manual browser management
  • Grid 4's GraphQL endpoint replaces the old JSON status API for monitoring and debugging
  • Node autoscaling with Kubernetes is possible but complex — cloud services (BrowserStack, LambdaTest) are often easier
  • Grid makes sense for teams with existing Selenium investments; new projects should evaluate Playwright first

What Is Selenium Grid?

Selenium Grid is a server-side component that allows you to run Selenium WebDriver tests on remote machines with different browsers. Instead of running tests locally, your test code sends WebDriver commands to a Grid hub, which routes them to an appropriate node — a machine with the requested browser installed.

The key benefits:

  • Parallel execution: Run the same test suite in Chrome, Firefox, and Edge simultaneously
  • Distributed execution: Spread tests across multiple machines to reduce total run time
  • Centralized management: One endpoint to manage all browser sessions
  • Remote execution: Tests run on dedicated machines separate from developer laptops

Selenium Grid 4 (current) is a complete rewrite of Grid 3 with improved architecture, better monitoring, and native container support.

Grid 4 Architecture

Grid 4 introduces three deployment modes depending on your scale requirements.

Standalone Mode

All Grid components run in a single process on a single machine. Suitable for local development and small teams.

┌─────────────────────────────────┐
│         Standalone              │
│  Router → Distributor → Node    │
│              ↓                  │
│         Session Map             │
└─────────────────────────────────┘

Hub and Node Mode

The traditional Grid topology. A central hub accepts test requests and routes them to registered nodes. Each node has browsers installed and accepts sessions.

Test Code → Hub → Node 1 (Chrome on Ubuntu)
                → Node 2 (Firefox on Ubuntu)
                → Node 3 (Edge on Windows)
                → Node 4 (Chrome + Firefox on macOS)

This is the most common deployment for on-premises cross-browser testing.

Fully Distributed Mode

Each Grid component (Router, Distributor, Session Map, Session Queue, Nodes) runs as a separate process or container. Designed for large-scale Kubernetes deployments.

Setting Up Selenium Grid 4

Prerequisites

  • Java 11 or higher
  • selenium-server-4.x.x.jar (download from selenium.dev)
  • Browser binaries and matching WebDriver executables
  • ChromeDriver, GeckoDriver (Firefox), EdgeDriver added to PATH

Standalone Mode (Quickstart)

java -jar selenium-server-4.x.x.jar standalone

Grid starts on http://localhost:4444. Point your WebDriver to this URL:

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

driver = webdriver.Remote(
    command_executor='http://localhost:4444/wd/hub',
    options=webdriver.ChromeOptions()
)

Hub and Node Setup

Start the Hub:

java -jar selenium-server-4.x.x.jar hub
# Hub starts on http://localhost:4444

Start Chrome Node:

java -jar selenium-server-4.x.x.jar node \
  --hub http://localhost:4444 \
  --port 5555

Start Firefox Node:

java -jar selenium-server-4.x.x.jar node \
  --hub http://localhost:4444 \
  --port 5556

Nodes register automatically with the hub. Visit http://localhost:4444/ui to see the Grid console and verify nodes are registered.

Requesting Specific Browsers

In your test code, specify which browser you want:

# Chrome
chrome_options = webdriver.ChromeOptions()
driver = webdriver.Remote(
    command_executor='http://localhost:4444',
    options=chrome_options
)

# Firefox
firefox_options = webdriver.FirefoxOptions()
driver = webdriver.Remote(
    command_executor='http://localhost:4444',
    options=firefox_options
)

# Edge
edge_options = webdriver.EdgeOptions()
driver = webdriver.Remote(
    command_executor='http://localhost:4444',
    options=edge_options
)

Grid routes each session to a node that has the requested browser available.

Docker Selenium Grid

Docker Selenium is the recommended way to run Grid in CI. Pre-built images handle browser installs, driver management, and VNC access for debugging.

Docker Compose Setup

version: '3.8'
services:

  selenium-hub:
    image: selenium/hub:4.20
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"

  chrome:
    image: selenium/node-chrome:4.20
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=5
    volumes:
      - /dev/shm:/dev/shm

  firefox:
    image: selenium/node-firefox:4.20
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=5
    volumes:
      - /dev/shm:/dev/shm

  edge:
    image: selenium/node-edge:4.20
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=5
    volumes:
      - /dev/shm:/dev/shm

Start the Grid:

docker compose up -d
# Hub UI: http://localhost:4444/ui

The /dev/shm volume mount is important — Chrome and Firefox use shared memory for rendering, and the default container limit (64MB) causes browser crashes. Mounting /dev/shm from the host gives each node the full shared memory.

Scaling Node Replicas

Scale individual browser nodes without touching the hub:

docker compose up -d --scale chrome=10 --scale firefox=5

This creates 10 Chrome nodes and 5 Firefox nodes, each capable of SE_NODE_MAX_SESSIONS parallel sessions. For 5 sessions per node, this gives you 50 parallel Chrome sessions and 25 parallel Firefox sessions.

Debug with VNC

Docker Selenium provides debug images with VNC servers for watching tests run:

chrome-debug:
  image: selenium/node-chrome:4.20
  # VNC password: secret
  ports:
    - "7900:7900"  # noVNC web interface

Access http://localhost:7900/?autoconnect=1&resize=scale&password=secret to watch the browser in your browser.

Grid in CI/CD

GitHub Actions with Docker Grid

name: Cross-Browser Tests
on: [pull_request]

jobs:
  selenium-grid:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Start Selenium Grid
        run: docker compose up -d
        working-directory: ./docker

      - name: Wait for Grid to be ready
        run: |
          for i in {1..30}; do
            if curl -s http://localhost:4444/status | grep -q '"ready":true'; then
              echo "Grid is ready"
              exit 0
            fi
            sleep 2
          done
          echo "Grid failed to start"
          exit 1

      - name: Run cross-browser tests
        run: pytest tests/ --browser=chrome --browser=firefox --browser=edge

      - name: Stop Grid
        if: always()
        run: docker compose down

Parallel Test Execution

With pytest, use pytest-xdist to run tests in parallel across browsers:

pytest tests/ -n 6  # 6 parallel workers

Combine with browser parametrization to run all tests × all browsers in parallel:

import pytest
from selenium import webdriver

@pytest.fixture(params=['chrome', 'firefox', 'edge'])
def driver(request):
    browser = request.param
    options = {
        'chrome': webdriver.ChromeOptions(),
        'firefox': webdriver.FirefoxOptions(),
        'edge': webdriver.EdgeOptions(),
    }[browser]

    driver = webdriver.Remote(
        command_executor='http://localhost:4444',
        options=options[browser]
    )
    yield driver
    driver.quit()

Monitoring Grid Health

Grid UI

Visit http://<hub-host>:4444/ui for the Grid console. It shows:

  • Registered nodes and their capabilities
  • Active sessions per node
  • Session queue depth
  • Node health status

GraphQL API

Grid 4 exposes a GraphQL endpoint at /graphql for programmatic monitoring:

curl -X POST http://localhost:4444/graphql \
  -H "Content-Type: application/json" \
  -d <span class="hljs-string">'{"query": "{ grid { totalSlots, usedSlots, sessionCount, nodes { id, status, sessionCount } } }"}'

Use this to build dashboards or integrate with alerting systems.

When to Use Selenium Grid vs Cloud Services

Use Selenium Grid When

  • You have existing Selenium test suites that would require significant rewriting to migrate
  • Compliance requirements prevent using external cloud services
  • You need specific browser versions or custom browser configurations
  • You run thousands of parallel tests and cloud pricing is prohibitive

Use Cloud Services (BrowserStack/LambdaTest) When

  • You need macOS/real iOS Safari testing (impossible with Docker Grid)
  • Your team doesn't have infrastructure expertise to maintain Grid
  • You want real physical device coverage
  • You need to scale elastically without capacity planning

Consider Playwright When

  • You are starting a new project without existing Selenium investment
  • You want simpler cross-browser setup without running infrastructure
  • You need WebKit/Safari coverage on Linux CI
  • You want the most maintainable long-term solution

HelpMeTest with Selenium Grid

Running Selenium Grid at scale requires infrastructure expertise and ongoing maintenance. HelpMeTest eliminates the infrastructure problem entirely — tests written in plain English run across browsers without any Grid setup. For teams that need to move quickly without dedicating engineering time to test infrastructure, HelpMeTest provides cross-browser coverage as a managed service.

Conclusion

Selenium Grid remains a powerful option for cross-browser testing at scale, particularly for teams with existing Selenium investments or on-premises requirements. Grid 4's Docker-native approach makes it easier to set up than ever — a Docker Compose file and five minutes is all it takes to have Chrome, Firefox, and Edge running in parallel.

For new projects, evaluate Playwright before investing in Grid infrastructure. Playwright's bundled browsers and simpler architecture deliver the same cross-browser coverage with less operational overhead. But for teams already in the Selenium ecosystem, Grid 4 with Docker Selenium is a robust, scalable solution that will serve you well.

Read more