browserstack-automate
Author and run E2E tests on BrowserStack Automate - cloud grid covering 3000+ real device + browser combinations. Covers BROWSERSTACK_USERNAME + ACCESS_KEY auth, hub URL https://hub-cloud.browserstack.com/wd/hub, W3C capabilities + bstack:options (projectName, buildName, sessionName), BrowserStackLocal for testing against localhost / internal environments, parallel session limits, and CI integration. Use for cross-browser regression on real devices + browsers - distinct from running a single test framework locally, and from a matrix runner limited to the browser engines bundled on the local machine.
Install with skills.sh (any agent)
npx skills add testland/qa --skill browserstack-automatebrowserstack-automate
Overview
BrowserStack Automate is a hosted Selenium / Playwright / Cypress grid that exposes 3000+ real device + browser combinations (iOS, Android, Windows, macOS) via a standard WebDriver-compatible endpoint. Per browserstack.com/docs/automate/selenium (opens in new window).
This skill wraps BrowserStack for Selenium-style invocation; Playwright + Cypress integrations follow a different (but similar) pattern documented separately by BrowserStack.
Composes with browser-matrix-strategy-reference (in the qa-compatibility plugin) for matrix planning.
When to use
For bundled-engine matrix (Chromium / Firefox / WebKit on the runner machine), use browser-matrix-runner. For orchestration across local + cloud grids, use a dedicated grid-orchestration layer.
How to use
Authentication
Per BrowserStack Automate docs, set env vars:
export BROWSERSTACK_USERNAME="your-username"
export BROWSERSTACK_ACCESS_KEY="<access-key-from-account-settings>"Hub URL
https://hub-cloud.browserstack.com/wd/hubConnect any WebDriver client (Selenium, WebdriverIO, Nightwatch) to this URL with the standard RemoteWebDriver-style construction.
Capabilities (W3C)
Standard W3C fields - browserName, browserVersion, platformName (or BrowserStack's non-standard os + osVersion) - plus a bstack:options block for BrowserStack-specific settings:
{
"browserName": "Chrome",
"browserVersion": "latest",
"os": "Windows",
"osVersion": "11",
"bstack:options": {
"projectName": "My App",
"buildName": "PR-1234",
"sessionName": "Login flow on Chrome Windows",
"local": "false"
}
}The exhaustive bstack:options table (debug, networkLogs, consoleLogs, video, seleniumVersion, ...) is in references/ci-and-scaling.md.
Worked example
Run one Selenium suite on the grid end to end - build capabilities, create the remote driver, drive the test, report status, quit:
import os
from selenium import webdriver
caps = {
"browserName": "Safari",
"browserVersion": "17",
"os": "OS X",
"osVersion": "Sonoma",
"bstack:options": {
"projectName": "my-app",
"buildName": os.environ.get("BUILD_TAG", "local-run"),
"sessionName": "Checkout flow on Safari macOS",
"local": "false",
},
}
driver = webdriver.Remote(
command_executor=(
f"https://{os.environ['BROWSERSTACK_USERNAME']}:"
f"{os.environ['BROWSERSTACK_ACCESS_KEY']}"
f"@hub-cloud.browserstack.com/wd/hub"
),
options=webdriver.SafariOptions(), # base options
)
# inject capabilities
for k, v in caps.items():
driver.capabilities[k] = v
driver.get("https://example.com")
# ... test ...
# mark the session pass / fail so the dashboard metrics are accurate
driver.execute_script(
'browserstack_executor: {"action": "setSessionStatus", '
'"arguments": {"status":"passed","reason":"Login redirected as expected"}}'
)
driver.quit()(Modern WebDriver clients prefer constructing through options + a capabilities dict; consult the chosen client's docs.) Use "status":"failed","reason":"..." on failure - the session-status call drives the BrowserStack dashboard's pass / fail metrics + filtering.
Local testing (BrowserStackLocal)
To run tests against localhost / internal environments, start the tunnel and set bstack:options.local = "true" on the session:
# Download the BrowserStackLocal binary from browserstack.com
./BrowserStackLocal --key "$BROWSERSTACK_ACCESS_KEY" --daemon start
# Sessions with bstack:options.local = "true" now tunnel
./BrowserStackLocal --key "$BROWSERSTACK_ACCESS_KEY" --daemon stopOr via Docker:
docker run --name bstacklocal -d --rm \
browserstack/local --key "$BROWSERSTACK_ACCESS_KEY"Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Credentials in code | Token leak | Env vars / secret store |
| All tests on every browser combo | Slow + expensive (plan-limited) | Tier the matrix - see browser-matrix-strategy-reference |
| Missing buildName | Sessions un-grouped in dashboard | Always set buildName to CI run / PR identifier |
| No session-status update | Dashboard pass/fail rate inaccurate | Always set session status before quit |
| BrowserStackLocal not stopped | Stale tunnels accumulate | Always daemon stop after test |
| Parallel exceeds plan limit | Sessions queue + timeout | Match MAX_PARALLEL to plan |
| Treating real-device dashboard as live | BrowserStack sessions can have minute-level setup latency | Build wait + retry around setup |
Limitations
References
BrowserStack Automate CI, scaling, and full capabilities
View source (opens in new window)BrowserStack Automate CI, scaling, and full capabilities
Deep reference for browserstack-automate SKILL.md. Consult when wiring BrowserStack into CI, scaling parallel sessions to a plan limit, tuning the full bstack:options capability set, or pulling session artifacts via REST.
Full bstack:options table
Per BrowserStack docs (browserstack.com/automate/capabilities), bstack:options carries BrowserStack-specific settings:
| Option | Purpose |
|---|---|
projectName | Group sessions by project (dashboard organisation) |
buildName | Group sessions by build / CI run |
sessionName | Human-readable session label |
local | "true" if testing localhost / internal via BrowserStackLocal |
debug | Enable visual debugging (screenshots + DOM) |
networkLogs | Capture HAR file |
consoleLogs | "errors" / "warnings" / "info" / "verbose" |
video | Default "true" - session video recording |
seleniumVersion | Pin a Selenium version (e.g., "4.21.0") |
Parallel session limits
BrowserStack plans limit parallel sessions (typically 5-50 per plan). Per their docs, queue overflow blocks subsequent sessions until earlier ones complete. Match the worker pool to the plan:
from concurrent.futures import ThreadPoolExecutor
MAX_PARALLEL = 5 # match plan
with ThreadPoolExecutor(max_workers=MAX_PARALLEL) as exe:
for case in cases:
exe.submit(run_case, case)Parsing results
BrowserStack session reports include:
Per the BrowserStack docs, retrieve sessions via REST API:
curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \
"https://api.browserstack.com/automate/sessions/<session-id>.json"Feed failure videos + HAR to bug-report-from-failure (in the qa-defect-management plugin) for triage.
CI integration
# .github/workflows/cross-browser.yml
on: pull_request
jobs:
bstack:
runs-on: ubuntu-latest
strategy:
matrix:
browser:
- { name: Chrome, version: latest, os: Windows, osVersion: "11" }
- { name: Safari, version: "17", os: "OS X", osVersion: Sonoma }
- { name: Firefox, version: latest, os: Windows, osVersion: "11" }
- { name: Edge, version: latest, os: Windows, osVersion: "11" }
steps:
- uses: actions/checkout@v5
- name: Run cross-browser tests
env:
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
BSTACK_BROWSER: ${{ matrix.browser.name }}
BSTACK_VERSION: ${{ matrix.browser.version }}
BSTACK_OS: ${{ matrix.browser.os }}
BSTACK_OS_VERSION: ${{ matrix.browser.osVersion }}
BUILD_TAG: pr-${{ github.event.pull_request.number }}
run: pytest tests/e2e/ --bstackMatch the matrix breadth to a tiered plan - see browser-matrix-strategy-reference for how to tier the matrix so full runs stay within the plan's parallel-session limit.
Related skills
cypress-testing
Authors and improves Cypress E2E tests - installs Cypress, configures `cypress.config.ts`, authors `cy.*` command chains, refactors existing specs (`cy.wait(ms)` sleeps into assertions, repeated flows into `cy.session` custom commands), and debugs with the time-travel GUI; Cypress Cloud for parallel runs and recording. Use for both greenfield test authoring and improving hand-written specs already in the codebase. For automated refactor of raw Cypress Studio recordings specifically, use a dedicated codegen-review pass.
lambdatest-automate
Author and run E2E tests on LambdaTest - cloud grid for cross-browser + real-device testing with W3C WebDriver, Cypress, Playwright, and Appium support. Covers LT_USERNAME + LT_ACCESS_KEY auth, hub URL hub.lambdatest.com/wd/hub, W3C capabilities + LT:Options dict (build, name, project, smartUI, network, console, video, tunnel), LambdaTest Tunnel for internal apps. Use for cross-browser regression with LambdaTest as the cloud grid; complements BrowserStack + Sauce Labs.
playwright-testing
Authors and remediates Playwright E2E tests across Chromium, Firefox, WebKit - `npm init playwright@latest` scaffolding, `playwright.config.ts` browser projects, accessibility-first locators (`getByRole`/`getByLabelText`) to replace brittle CSS selectors, web-first assertions to eliminate `waitForTimeout` flakiness, Page Object pattern, trace viewer debugging, sharded parallel execution with merged HTML reporting, and GitHub Actions CI integration. Use for new test authoring, flakiness remediation, and CI setup; for reviewing codegen output specifically, use a dedicated codegen-review pass.
puppeteer-testing
Authors browser automation scripts using Puppeteer - Chrome / Chromium-only headless / headed automation, Page object via `page.*` API, network interception, PDF generation, screenshot capture, scraping. Distinct from Playwright (Puppeteer's older sibling, Chrome-only) - use Puppeteer for Chrome-only browser automation tasks (scraping, generating PDFs from HTML, screenshot pipelines) where Playwright's multi-browser support is unneeded overhead. Use when a project already depends on `puppeteer` / `puppeteer-core`, or when a Chrome-only script must emit PDFs, screenshots, or scraped data rather than assert on a page.
saucelabs-automate
Author and run E2E tests on Sauce Labs - cloud grid for cross-browser + real-device testing with W3C WebDriver, Cypress, Playwright, and Appium support. Covers SAUCE_USERNAME + SAUCE_ACCESS_KEY auth, regional hub URLs (us-west-1 / us-east-4 / eu-central-1), W3C capabilities, sauce:options dict (build, name, screenResolution, tunnelName), Sauce Connect Proxy for internal-environment testing. Use for cross-browser regression with Sauce Labs as the cloud grid; complements BrowserStack + LambdaTest as alternative providers.
selenium-testing
Authors Selenium WebDriver tests in any of its 6+ supported languages (Java, Python, JavaScript, C#, Ruby, Kotlin, PHP) - picks the appropriate language binding, configures WebDriver per browser, uses `By.*` locators with the team's accessibility-first preference where supported, runs locally + via Selenium Grid for distributed execution, parses results to JUnit XML. Use for legacy Selenium-locked stacks; new projects pick Playwright or Cypress.
testcafe-testing
Authors TestCafe E2E tests - `npm install testcafe`, fixture/test syntax, `Selector` API for queries, automatic-waits, no WebDriver required (TestCafe injects scripts via a proxy), supports any browser including remote / cloud farms. Use when the team prefers a no-WebDriver architecture and one of TestCafe's specific features (e.g., role-based auth) matters.
web-e2e-overview
Teaches web end-to-end testing from first principles: what browser-driven E2E covers and how it differs from unit and integration tests, a decision table for choosing between Playwright, Cypress, Selenium WebDriver, WebdriverIO, Puppeteer, TestCafe and the BrowserStack / Sauce Labs / LambdaTest cloud grids based on files already present in the repo, install and first-run commands for each, and the flakiness traps (fixed sleeps, CSS and XPath selectors, state shared between tests) that sink new suites. Use when a web application has no E2E coverage yet, when picking or replacing an E2E framework, or when a first browser test needs to go green end to end.
webdriverio-testing
Authors WebdriverIO E2E tests - `npm init wdio@latest` scaffolding, services architecture (sauce, browserstack, appium, devtools), reporters (spec, allure, junit), built-in Mocha/Jasmine/Cucumber framework integrations. WebdriverIO sits between Selenium (W3C protocol) and Playwright (modern API) - Selenium-protocol-compatible with rich plugin ecosystem. Use when the team needs WebDriver protocol + service-based device-farm integration.