ScreenshotNeo

BlogHow-to

How to automate BrowserStack screenshots with Selenium

Use BrowserStack Visual Logs for automatic session screenshots, or capture and save exact checkpoints with Selenium. Includes Python, JavaScript, and CI guidance.

By the ScreenshotNeo team4 October 20269 min read

There are two ways to automate screenshots in BrowserStack Automate with Selenium: enable Visual Logs to capture screenshots during Selenium commands and view them in the Automate dashboard, or call Selenium’s screenshot API at a chosen checkpoint and save an image on the test runner. Use Visual Logs to inspect a session as it runs; use an explicit screenshot call when your CI job needs to retain or publish a specific image.

This guide shows both approaches, how to preserve files in CI, and how screenshots differ from BrowserStack videos and logs. The instructions and capabilities below follow BrowserStack’s screenshot and debugging documentation and its capability reference.

1. Choose the screenshot path

Need Use Where the result goes
See page state around Selenium commands, especially during failure investigation Visual Logs, enabled with the debug capability BrowserStack Automate dashboard
Capture a deliberately selected page state or retain an image as a CI artifact Selenium screenshot API File or bytes on the test runner; CI must preserve or upload it
Replay the session over time Video logs Automate session results; video is separate from a screenshot file

Visual Logs are automatic dashboard evidence. They are not downloaded to the test machine by the screenshot call. An explicit screenshot gives the test control over when to capture and where to save; it does not automatically become a retained CI artifact unless the pipeline uploads it. BrowserStack says video is enabled by default and can add a slight execution-time increase. See the debugging options for current behavior.

2. Enable automatic screenshots with Visual Logs

Visual Logs are disabled by default. Set debug to the string "true" in BrowserStack capabilities. For a W3C Selenium session, put it inside bstack:options.

Python with Selenium

import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.browser_version = "latest"
options.set_capability("bstack:options", {
    "debug": "true",
    "os": "Windows",
    "osVersion": "11",
    "sessionName": "Visual Logs example",
    "buildName": "screenshot-guide",
})

# Set BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY in the environment.
username = os.environ["BROWSERSTACK_USERNAME"]
access_key = os.environ["BROWSERSTACK_ACCESS_KEY"]
options.set_capability(
    "browserName", "Chrome"
)

driver = webdriver.Remote(
    command_executor=f"https://{username}:{access_key}@hub-cloud.browserstack.com/wd/hub",
    options=options,
)
try:
    driver.get("https://example.com")
    print(driver.title)
finally:
    driver.quit()

Install the Selenium Python package with python -m pip install selenium. Create BrowserStack credentials in your account and set them as environment variables before running the script. The remote endpoint and credential setup should match the BrowserStack account and integration you use.

Legacy capability format

For an integration still using BrowserStack’s legacy capability names, the equivalent documented flag is browserstack.debug: "true". Do not send both formats blindly: use the format expected by your Selenium client and integration. Check BrowserStack’s capabilities guide if the session rejects a capability.

Find automatic screenshots

  1. Run the test and note the Automate build or session identifier.
  2. Open that session in the BrowserStack Automate dashboard.
  3. Inspect the session’s available Visual Logs and related debugging evidence.

Dashboard wording and layout can change, so identify the result by its build or session rather than depending on a fixed tab name. BrowserStack documents that Visual Logs are unsupported on its macOS Snow Leopard and Lion computers; verify support for the exact browser and operating system you target.

3. Capture an explicit screenshot file with Selenium

Call the driver screenshot method after the page reaches the state you want to preserve. The following Python example uses a local Chrome session so the capture code runs as-is after installing Selenium and ChromeDriver compatible with your Chrome version.

from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait

output = Path("artifacts")
output.mkdir(parents=True, exist_ok=True)

options = Options()
options.add_argument("--headless=new")

driver = webdriver.Chrome(options=options)
try:
    driver.get("https://example.com")
    WebDriverWait(driver, 15).until(
        lambda d: d.execute_script("return document.readyState") == "complete"
    )
    saved = driver.save_screenshot(str(output / "example.png"))
    if not saved:
        raise RuntimeError("Selenium did not save the screenshot")
finally:
    driver.quit()

save_screenshot(path) writes an image on the machine running the driver. With a remote WebDriver such as BrowserStack, the Selenium binding returns the screenshot to the client and saves it at the path supplied by your test. Ensure the client process has a writable directory and upload the file before CI tears down the workspace.

JavaScript with Selenium WebDriver

Install the binding with npm install selenium-webdriver and have a compatible browser driver available. This local Chrome example writes the PNG bytes returned by Selenium:

const fs = require('node:fs/promises');
const { Builder, By, until } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');

(async () => {
  const options = new chrome.Options().addArguments('--headless=new');
  const driver = await new Builder()
    .forBrowser('chrome')
    .setChromeOptions(options)
    .build();

  try {
    await driver.get('https://example.com');
    await driver.wait(until.elementLocated(By.css('h1')), 15000);
    const png = await driver.takeScreenshot();
    await fs.mkdir('artifacts', { recursive: true });
    await fs.writeFile('artifacts/example.png', png, 'base64');
  } finally {
    await driver.quit();
  }
})().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

For a BrowserStack remote session, configure the WebDriver builder with the remote hub and the capabilities for your account, then use the same takeScreenshot() call. BrowserStack’s screenshot documentation also includes examples for Java, C#, PHP, and Ruby; method syntax depends on the language binding.

Capture timing matters

  • Navigate, then wait for a meaningful condition such as a visible element or application state. A completed navigation does not guarantee that client-rendered content, fonts, animations, or lazy images are ready.
  • Capture after dismissing or accepting test dialogs if the desired artifact is the post-interaction state.
  • For a failure screenshot, capture in the test’s failure handler before calling quit(); after the session closes there is no active page to capture.
  • Use distinct filenames per test, worker, browser, and retry so parallel runs do not overwrite each other.

4. Preserve screenshots in CI

A screenshot saved by Selenium belongs to the runner’s filesystem. CI systems usually discard that filesystem after a job unless the workflow uploads the file as an artifact. Create the output directory, save the image, upload it even when the test fails, and retain the BrowserStack session identifier alongside it for correlation.

# Example shell step after the test process has produced artifacts/*.png
# Configure your CI provider's artifact-upload action/task to upload this directory.
find artifacts -maxdepth 1 -type f -name '*.png' -print

The upload action is provider-specific, so add the artifact-retention step supported by your CI platform. Configure it to run after failures as well as successful tests. If the test runs in a container, write into a mounted workspace directory that the CI runner can access.

5. Screenshots, videos, and logs are different evidence

  • Visual Logs: automatic screenshots associated with commands and viewed in the Automate dashboard.
  • Explicit screenshot: an image captured at a point selected by test code and returned to the test runner.
  • Video: a recording useful for replaying session execution; it is not a still image and has a separate retrieval path.
  • Selenium command logs: records of actions and commands, not page images.
  • Network and console logs: additional diagnostic data with their own capability settings and browser/platform support.

BrowserStack’s capability reference lists debug as false by default, video as true, seleniumLogs as true, and networkLogs as false. Availability and exceptions can depend on browser and platform, so check the live capability reference for the precise target combination. Optional logging can add work to a session; enable only the evidence needed for the investigation.

6. Troubleshooting

Symptom Likely cause Fix
No Visual Logs in the session debug is unset, false, or placed outside bstack:options for a W3C session Set "debug": "true" in the correct capability namespace and start a new session.
Capability is rejected or ignored Legacy and W3C capability formats are mixed, or a name/value is invalid Use the capability format supported by the client/integration and confirm names in BrowserStack’s current reference.
Screenshot is missing from CI artifacts The runner workspace was cleaned, the output path was outside the workspace, or upload did not run after failure Save under the job workspace and configure artifact upload to run on both success and failure before teardown.
Screenshot is blank or shows an earlier state Capture happened before the page or asynchronous UI was ready Wait for a specific visible element or state, and capture after the relevant interaction.
Screenshot save fails Target directory does not exist or is not writable Create the directory first, use an absolute or workspace-relative path, and check the return value or exception.
Cannot find the screenshot in the dashboard Looking at the wrong build/session or expecting dashboard Visual Logs to be a local file Use the session/build identifier; use an explicit Selenium screenshot call for a runner-side file.
Debug evidence differs by target platform Some logging options have browser/OS exceptions; Visual Logs do not support the cited old macOS targets Check the current capability support for that exact browser and OS.

7. Performance, reliability, and cost considerations

Each explicit capture transfers image data to the Selenium client and writes it to storage, so capture only useful checkpoints in large suites and avoid producing the same image repeatedly on every passing step. Automatic Visual Logs are convenient for command-level investigation, but they add debugging data to the session and are retrieved from the dashboard. Video is useful for timelines; BrowserStack notes a slight execution-time increase for video logs. No fixed latency or storage benchmark is implied here because the result depends on the target browser, page, and session configuration.

For reliable artifacts, wait on application-specific conditions rather than arbitrary short sleeps, save to a job workspace, use collision-resistant names in parallel suites, and upload artifacts in an always-run/finally CI step. Keep the BrowserStack build and session identifiers in test output so an image can be connected to the remote execution. BrowserStack Automate pricing and plan limits depend on the current account offering; consult BrowserStack directly for applicable charges and retention terms rather than inferring them from screenshot capabilities.

8. Or skip the browser setup

If you need a screenshot of a public webpage outside a Selenium test, ScreenshotNeo returns an image or PDF from one GET request. Its API accepts the URL and supports PNG, JPEG, or WebP output. See the ScreenshotNeo API docs for the request options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie and consent banners are accepted and removed before capture; more than 60 known consent platforms, newsletter popups, and chat widgets can be removed, with each step configurable.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers report the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
  • The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Create a free ScreenshotNeo account to get 1,000 screenshots per month with no card.

9. Frequently asked questions

Does enabling Visual Logs save a PNG into my repository?

No. Visual Logs are available in the BrowserStack Automate dashboard. Use Selenium’s screenshot API to create a file in the runner workspace.

Can I capture only when a test fails?

Yes. In the test framework’s failure hook, call the active driver’s screenshot method before quitting the session, then upload the resulting file as an artifact.

Are screenshots the same as BrowserStack video?

No. A screenshot is a still image at a point in the test; video records session activity over time, and command logs record actions.

Will the same debugging options work on every browser and OS?

Not necessarily. Check BrowserStack’s current capability documentation for the specific browser and operating system combination.