BrowserStack Automate: Running Selenium and Playwright Tests in the Cloud
BrowserStack Automate lets you run your Selenium and Playwright tests against a cloud grid of real browsers and operating systems. Instead of managing your own browser infrastructure or Selenium Grid, you point your tests at BrowserStack's remote WebDriver endpoint and they handle the rest.
This guide covers setup, configuration, parallel execution, CI/CD integration, and the practical patterns that make cloud testing work at scale.
How BrowserStack Automate Works
Your test code runs locally (or in your CI pipeline). When Selenium or Playwright initializes a browser session, instead of launching a local browser, it connects to BrowserStack's remote WebDriver endpoint. BrowserStack starts the requested browser on their infrastructure, and your test drives it over the network.
From your test's perspective, it's just a RemoteWebDriver — the same API as local WebDriver. The difference is you can request any browser/OS combination in BrowserStack's catalog without that browser being installed locally.
Setting Up Selenium with BrowserStack
Install the WebDriver client:
# Java
# Add to pom.xml or build.gradle (selenium-java)
# Python
pip install selenium
# Node.js
npm install selenium-webdriver
# C#
dotnet add package Selenium.WebDriverPython example:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
options = webdriver.ChromeOptions()
bstack_options = {
"browserName": "chrome",
"browserVersion": "latest",
"os": "Windows",
"osVersion": "11",
"buildName": "My First Build",
"sessionName": "BStack Sample Test",
"userName": "your_username",
"accessKey": "your_access_key"
}
options.set_capability("bstack:options", bstack_options)
driver = webdriver.Remote(
command_executor="https://hub-cloud.browserstack.com/wd/hub",
options=options
)
try:
driver.get("https://example.com")
assert "Example" in driver.title
finally:
driver.quit()JavaScript/Node.js example:
const { Builder } = require('selenium-webdriver');
const capabilities = {
'browserName': 'chrome',
'browserVersion': 'latest',
'bstack:options': {
'os': 'Windows',
'osVersion': '11',
'buildName': 'My Build',
'sessionName': 'My Test',
'userName': process.env.BROWSERSTACK_USERNAME,
'accessKey': process.env.BROWSERSTACK_ACCESS_KEY
}
};
const driver = await new Builder()
.usingServer('https://hub-cloud.browserstack.com/wd/hub')
.withCapabilities(capabilities)
.build();
try {
await driver.get('https://example.com');
const title = await driver.getTitle();
console.assert(title.includes('Example'));
} finally {
await driver.quit();
}Browser and OS Capabilities
Specify the target environment through capabilities:
bstack_options = {
# Browser
"browserName": "chrome", # chrome, firefox, safari, edge
"browserVersion": "latest", # latest, latest-1, specific version like "120.0"
# OS
"os": "Windows", # Windows, OS X
"osVersion": "11", # 10, 11 for Windows; Sonoma, Ventura, Monterey for macOS
# OR use a device name for specific hardware
# "os": "OS X",
# "osVersion": "Sonoma",
# "browserName": "safari",
}Use BrowserStack's Capabilities Generator to find the right values for your target combinations.
Running Playwright on BrowserStack
BrowserStack supports Playwright natively:
npm install -D @browserstack/playwright-browserstack// playwright.config.js
const { devices } = require('@playwright/test');
module.exports = {
use: {
connectOptions: {
wsEndpoint: `wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify({
browser: 'playwright-chromium',
browser_version: 'latest',
os: 'osx',
os_version: 'ventura',
name: 'My Playwright Test',
build: 'Playwright Build 1',
'browserstack.username': process.env.BROWSERSTACK_USERNAME,
'browserstack.accessKey': process.env.BROWSERSTACK_ACCESS_KEY,
}))}`,
},
},
};Or use the BrowserStack SDK which handles configuration automatically:
npm install -D browserstack-node-sdk# browserstack.yml
userName: your_username
accessKey: your_access_key
browsers:
- browser: chrome
os: Windows
osVersion: 11
browserVersion: latest
- browser: firefox
os: OS X
osVersion: Ventura
browserVersion: latest
- browser: safari
os: OS X
osVersion: Ventura
browserVersion: latest
framework: playwright
parallelsPerPlatform: 2Then run:
npx browserstack-node-sdk playwright testParallel Execution
BrowserStack's main value for automation is running tests in parallel across browsers. Without parallel execution, running tests against 5 browsers takes 5× as long.
Configure parallelism based on your plan's concurrent session limit:
Pytest (Python):
pip install pytest-xdist
# pytest.ini
[pytest]
addopts = -n 5 # 5 parallel processes
# In your fixture, parameterize browser selectionTestNG (Java):
<!-- testng.xml -->
<suite name="Cross Browser Suite" parallel="tests" thread-count="5">
<test name="Chrome Windows">
<parameter name="browser" value="chrome"/>
<parameter name="os" value="Windows"/>
<classes>
<class name="com.example.tests.CheckoutTests"/>
</classes>
</test>
<test name="Firefox macOS">
<parameter name="browser" value="firefox"/>
<parameter name="os" value="OS X"/>
<classes>
<class name="com.example.tests.CheckoutTests"/>
</classes>
</test>
</suite>Playwright:
// playwright.config.js
module.exports = {
workers: 5, // Parallel workers
projects: [
{ name: 'chrome-windows', use: { ...chromiumOnWindows } },
{ name: 'firefox-macos', use: { ...firefoxOnMac } },
{ name: 'safari-macos', use: { ...safariOnMac } },
],
};Local Testing (Testing Localhost)
Test against staging environments or localhost using the BrowserStack Local tunnel:
# Install
npm install -g browserstack-local
# Start tunnel
BrowserStackLocal --key $BROWSERSTACK_ACCESS_KEY --local-identifier my-tunnelIn your test capabilities:
bstack_options = {
# ... other options
"local": True,
"localIdentifier": "my-tunnel"
}For CI pipelines, use the GitHub Action:
- name: Start BrowserStack Local
uses: browserstack/github-actions/setup-local@v1
with:
local-testing: start
local-identifier: my-tunnel
local-logging-level: all-logs
env:
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}CI/CD Integration
GitHub Actions:
name: Cross-Browser Tests
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Start BrowserStack Local
uses: browserstack/github-actions/setup-local@v1
with:
local-testing: start
env:
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
- name: Run tests on BrowserStack
run: npx browserstack-node-sdk playwright test
env:
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
BUILD_NAME: "GitHub Actions - ${{ github.sha }}"
- name: Stop BrowserStack Local
uses: browserstack/github-actions/setup-local@v1
if: always()
with:
local-testing: stop
env:
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}Test Observability: Builds and Sessions
BrowserStack organizes test runs into Builds (CI run or test suite) and Sessions (individual test cases). Mark your builds and sessions correctly to get useful reporting:
bstack_options = {
"buildName": f"main-{os.environ.get('GITHUB_SHA', 'local')[:8]}",
"sessionName": "checkout_flow_chrome",
"buildTag": "regression", # tag for filtering
}In the BrowserStack Automate dashboard, you'll see:
- Pass/fail per session
- Session video recordings
- Network logs
- Console logs
- Visual diff screenshots
Marking Test Status
Mark the session as passed or failed from your test code so the dashboard reflects real results:
# Python (in test teardown)
if test_passed:
driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status": "passed", "reason": "All assertions passed"}}')
else:
driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status": "failed", "reason": "Assertion failed: checkout total incorrect"}}')// JavaScript
await driver.executeScript(`browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"${status}","reason":"${reason}"}}`);Performance Testing
BrowserStack Automate captures performance metrics:
- Page load time
- First contentful paint
- Time to interactive
- Network waterfall
Enable performance logging in capabilities:
bstack_options = {
"networkLogs": True,
"consoleLogs": "info", # errors, warnings, info, verbose
"seleniumLogs": True,
}Smart Test Reruns and Flakiness
BrowserStack's Test Observability product (add-on) includes:
- Flakiness analysis across builds
- Automatic rerun of failed tests
- Root cause analysis using ML (network failure vs. assertion failure vs. timeout)
This is similar to what Testmo does for results tracking, but built into BrowserStack.
Cost Optimization
BrowserStack pricing scales with:
- Parallel sessions: More concurrent sessions = higher cost
- Build minutes: Total time tests run
- Team size: Some plans are per-user
To optimize:
- Only run the full cross-browser matrix on main branch merges — not every PR
- Run smoke tests on PRs (2–3 browsers), full regression on merge
- Use
latestandlatest-1for browser versions rather than testing every version - Kill sessions immediately when tests fail rather than waiting for full suite completion
Summary
BrowserStack Automate is a mature cloud testing platform that takes the infrastructure management out of cross-browser testing. The remote WebDriver endpoint works with any Selenium or Playwright codebase with minimal changes — swap new ChromeDriver() for RemoteWebDriver with BrowserStack capabilities, and your existing tests run in the cloud.
The main considerations are cost (parallel sessions add up quickly) and network latency (remote execution is slower than local). For teams that need to test across browsers and don't want to maintain a Selenium Grid, BrowserStack Automate is the practical solution.