ScreenshotNeo

BlogHow-to

Recording Browser Automation Sessions: Video, Traces, and Replayable Tests

Choose the right browser-session artifact: Playwright video, trace archives, or Selenium IDE commands, with runnable setup and troubleshooting.

By the ScreenshotNeo team1 October 20267 min read

“Record a browser automation session” can mean three different outputs:

  • Video for visual playback and sharing.
  • A trace for step-by-step failure diagnosis.
  • Recorded commands that you can edit and replay as a test.

Use Playwright video when you need a movie of the run, Playwright Trace Viewer when you need timing, locators, DOM snapshots, and action details, and Selenium IDE when you want to capture browser actions as editable test commands.

Choose the artifact before you record

Artifact Best for How you inspect it Capture policy
Playwright video Visual replay, bug reports, demos Any video player Every test, retries, or failure-retained
Playwright trace Diagnosing a failed test Playwright Trace Viewer Off, always, retries, or retain on failure
Selenium IDE recording Creating and editing replayable browser commands Selenium IDE playback and editor Manual recording in a browser extension

This distinction matters: a video shows what the browser looked like, a trace explains what Playwright did and when, and an IDE recording gives you commands you can edit into a test.

Record video with Playwright Test

Playwright Test video recording is off by default. Set the video option in your test configuration to on, retain-on-failure, or on-first-retry. The supported values also include off.

Install and configure

npm init playwright@latest
# Select your language and test directory during the prompts

In playwright.config.ts:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    baseURL: 'https://example.com',
    video: 'retain-on-failure',
  },
});

Then create a test such as tests/session.spec.ts:

import { test, expect } from '@playwright/test';

test('records a checkout flow', async ({ page }) => {
  await page.goto('/');
  await page.getByRole('link', { name: 'Products' }).click();
  await expect(page).toHaveTitle(/Products/);
});

Run the test:

npx playwright test

With retain-on-failure, successful-run videos are discarded while videos from failed tests are kept. Use on when every run must have a video, or on-first-retry when you mainly need evidence for flaky tests.

Record video in a manually created browser context

When you create a context yourself, pass recordVideo. The video file is finalized when the browser context closes, so close and await the context before reading or uploading the file.

import { chromium } from 'playwright';

const browser = await chromium.launch();
const context = await browser.newContext({
  recordVideo: {
    dir: 'artifacts/videos',
    size: { width: 1280, height: 720 },
  },
});

const page = await context.newPage();
await page.goto('https://example.com');
await page.getByRole('link', { name: 'More information...' }).click();

await context.close(); // required to finalize the video
await browser.close();

The Browser API documents the output directory and optional video size settings. Keep the output directory outside your source tree or clean it in CI after uploading artifacts.

Record only selected tests

You can override the project setting for a single test:

import { test } from '@playwright/test';

test.use({ video: 'on' });

test('always keeps a video for this diagnostic test', async ({ page }) => {
  await page.goto('https://example.com');
});

Capture a diagnostic trace with Playwright

A trace contains more context than a video: actions, locator information, timing, action logs, source locations, DOM snapshots, and, when screenshots are enabled, screencast frames. Open a saved archive with the Playwright Trace Viewer.

Trace modes in Playwright Test

Run a suite with tracing enabled:

npx playwright test --trace on

For routine CI, choose a narrower policy:

# Capture the first retry of a failing test
npx playwright test --trace on-first-retry

# Capture every retry
npx playwright test --trace on-all-retries

# Keep traces only for failed tests
npx playwright test --trace retain-on-failure

# Disable tracing
npx playwright test --trace off

Playwright describes tracing every test as performance-heavy. Select a mode according to how often your team needs artifacts and how much capture overhead your pipeline can accept.

Trace a manually managed context

Without the Playwright Test runner, use the BrowserContext tracing API:

import { chromium } from 'playwright';

const browser = await chromium.launch();
const context = await browser.newContext();

await context.tracing.start({
  screenshots: true,
  snapshots: true,
  sources: true,
});

const page = await context.newPage();
await page.goto('https://example.com');
await page.getByRole('link', { name: 'More information...' }).click();

await context.tracing.stop({ path: 'artifacts/trace.zip' });
await context.close();
await browser.close();

Open the archive locally:

npx playwright show-trace artifacts/trace.zip

The hosted Trace Viewer processes the trace in your browser and states in the Playwright documentation that it does not transmit trace data externally. Treat the ZIP as sensitive test data anyway: it can contain page content, DOM snapshots, headers, or screenshots captured during the run.

What to inspect in Trace Viewer

  1. Use the timeline to find the first slow or failed action.
  2. Open the action entry to inspect the locator, duration, and action log.
  3. Compare before and after DOM snapshots to see what changed.
  4. Check the source location to jump back to the test code.
  5. When screenshots are enabled, use screencast frames to correlate visual state with the action.

Record browser commands with Selenium IDE

Selenium IDE is a browser extension for recording and playing back user actions. The Selenium documentation lists Chrome, Firefox, and Edge support.

  1. Install Selenium IDE for a supported browser.
  2. Create a new project and set its base URL.
  3. Open the browser window from the IDE.
  4. Interact with the site while recording: navigate, click, type, and submit.
  5. Return to Selenium IDE and stop the recording.
  6. Edit commands, add assertions, and replay the test.

This workflow records an editable command sequence rather than a video file or a Playwright trace. It is useful when the goal is to bootstrap a replayable test from real interactions.

Combine video and traces for failures

For a failed CI test, a trace usually gives the fastest diagnosis; a video is useful when a human reviewer needs a visual replay. A practical configuration is:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    trace: 'retain-on-failure',
    video: 'retain-on-failure',
  },
});

If storage is limited, keep traces on failures and enable videos only for selected projects or tests. If failures are rare but flaky retries are common, use on-first-retry for both artifacts.

Common problems and fixes

Symptom Cause Fix
No video file appears The context was not closed, or video is still off. Set a video mode and await context.close() before reading the file.
Video exists but is empty or incomplete The process ended before context finalization. Close the context in a finally block and wait for it before browser shutdown.
Trace is missing screenshots Tracing started without screenshot capture. Use screenshots: true in context.tracing.start().
Trace Viewer cannot open the archive The ZIP path is wrong or the trace was not stopped cleanly. Confirm the file exists, call tracing.stop({ path }), and rerun npx playwright show-trace.
CI runs become noticeably slower Tracing every test and retaining every artifact adds capture and storage work. Use on-first-retry or retain-on-failure; record only diagnostic projects.
Recorded commands fail on replay Selectors depend on changing text, timing, or session state. Replace brittle selectors, add explicit assertions or waits, and create stable test data.
Artifacts expose private data Videos and traces can contain page content, DOM snapshots, cookies, or tokens shown in the UI. Use test accounts, redact sensitive values, restrict artifact access, and set retention limits.

Performance, reliability, and storage decisions

  • Choose the smallest artifact that answers the question. A video is often enough for a visual bug; a trace is better for locator and timing failures.
  • Prefer retry- or failure-focused capture in CI. Playwright documents tracing every test as performance-heavy.
  • Finalize before upload. Close the browser context before your CI step archives video files.
  • Keep artifact names tied to test identity. Include project, browser, test name, retry number, and commit in your CI metadata.
  • Control retention. Videos and traces grow with test count and page complexity; expire old artifacts and upload only the files needed for diagnosis.
  • Make failures reproducible. Record browser version, viewport, locale, timezone, and test data identifiers alongside the artifact.

Or skip the browser setup

If you only need a clean screenshot of a page for a report, visual regression input, or an automation step, ScreenshotNeo returns an image or PDF from one GET request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

See the ScreenshotNeo API documentation for all options.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));

ScreenshotNeo also supports full-page captures with lazy images loaded, element selectors, dark mode, device presets, custom viewports, retina scale, PDF settings, custom CSS and JavaScript, click and wait actions, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification.

Plans include 1,000 free shots each month with no card; paid plans start at $5 for 3,000 shots. Every feature is available on every plan. Create a free ScreenshotNeo account.

FAQ

Should I record video or a trace?

Use video for visual playback. Use a trace when you need action timing, locator details, DOM snapshots, and source locations.

Does Playwright record video by default?

No. The default video mode is off; set a supported mode in configuration or on a test.

When is a Playwright video finalized?

After the browser context closes. Await that closure before copying or uploading the file.

Can Selenium IDE export a video?

Selenium IDE records browser commands for playback and editing. Use Playwright video when you need a video artifact.

Can a screenshot replace a session recording?

A screenshot captures one state. It cannot replace a video, trace, or command recording when you need the sequence of interactions.