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 standaloneGrid 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:4444Start Chrome Node:
java -jar selenium-server-4.x.x.jar node \
--hub http://localhost:4444 \
--port 5555Start Firefox Node:
java -jar selenium-server-4.x.x.jar node \
--hub http://localhost:4444 \
--port 5556Nodes 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/shmStart the Grid:
docker compose up -d
# Hub UI: http://localhost:4444/uiThe /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=5This 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 interfaceAccess 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 downParallel Test Execution
With pytest, use pytest-xdist to run tests in parallel across browsers:
pytest tests/ -n 6 # 6 parallel workersCombine 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.