Playwright Trace Viewer, Reports & Debugging

A failing test is only useful if you can see why it failed. Playwright ships everything needed for that: reporters for humans and CI, a Trace Viewer that replays every step of a run, UI mode and the Inspector for step-by-step debugging, and automatic screenshots and videos. This guide shows how to set them up in one config and which tool to reach for in each situation.

A Working Configuration

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  retries: process.env.CI ? 1 : 0,
  reporter: [
    ['list'],                                                  // console output
    ['html', { open: 'never', outputFolder: 'playwright-report' }],
    ['junit', { outputFile: 'results/junit.xml' }],            // for Jenkins / Azure DevOps / GitLab
  ],
  use: {
    baseURL: 'https://www.saucedemo.com',
    trace: 'on-first-retry',          // record a trace when a failed test is retried
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
  },
  projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
});

This is the typical setup: humans read the HTML report, CI reads the JUnit XML, and every failure comes with a trace, screenshot and video.

Reporters

Reporter Output Typical use
list One line per test in the console Local runs (the default locally)
line / dot Compact console output Large suites, CI logs
html Interactive report with steps, errors, attachments and traces Debugging and sharing results
junit JUnit XML CI test-result trends
json Machine-readable results Custom dashboards
blob Mergeable results Combining sharded CI runs into one report

Allure and other third-party reporters plug in the same way. Open the HTML report with:

Advertisement
npx playwright show-report

Interview answer: "Playwright has built-in list, line, dot, HTML, JSON, JUnit and blob reporters, and you can run several at once. We used the HTML report for debugging — it shows each step, the error, screenshots, videos and the trace — and JUnit XML so Jenkins could track results over time."

Make Reports Readable: Steps and Attachments

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

test('checkout shows the order summary', async ({ page }, testInfo) => {
  await test.step('log in', async () => {
    await page.goto('/');
    await page.locator('#user-name').fill('standard_user');
    await page.locator('#password').fill('secret_sauce');
    await page.locator('#login-button').click();
  });

  await test.step('add a product to the cart', async () => {
    await page.locator('[data-test="add-to-cart-sauce-labs-backpack"]').click();
    await expect(page.locator('[data-test="shopping-cart-badge"]')).toHaveText('1');
  });

  await testInfo.attach('cart-state', {
    body: JSON.stringify({ items: 1 }, null, 2),
    contentType: 'application/json',
  });

  // await page.pause();   // uncomment to stop here and open the Inspector
});

test.step groups actions into named steps in the report and trace, so a failure reads "failed in add a product to the cart" instead of line 14. testInfo.attach adds any evidence — API responses, logs, files.

Trace Viewer ⭐

A trace is a recording of a test run: every action, a DOM snapshot before and after each step, console logs, network requests and the source line. The Trace Viewer replays it like CCTV footage after an incident — you can hover over each step and see exactly what the page looked like.

Setting Records Use
'off' Nothing Fastest
'on' Every test Short debugging sessions only — heavy
'retain-on-failure' Every test, keeps failures only When retries are disabled
'on-first-retry' Only the first retry of a failed test ⭐ The usual CI setting
npx playwright test --trace on                       # force tracing for one run
npx playwright show-trace test-results/…/trace.zip   # open a trace locally

You can also drag a trace.zip into trace.playwright.dev — it opens in the browser without installing anything, which is handy for traces downloaded from CI.

What the Trace Viewer shows

  • Actions timeline with duration of each step.
  • Before / after DOM snapshots — inspect the page as it was.
  • Locator used and why an action waited or failed.
  • Console messages and errors.
  • Network requests with status and timing.
  • Source — the test line for each action.

Debugging Tools — Which to Use When

Situation Tool How
Writing or fixing a test locally UI mode npx playwright test --ui — watch mode, time-travel through steps, pick locators
Stepping through a test action by action Debug mode + Inspector npx playwright test login.spec.ts --debug (or PWDEBUG=1)
Stopping at one specific point page.pause() Add await page.pause(); run headed
Just watching the browser Headed mode npx playwright test --headed
Finding a locator Codegen / Inspector picker npx playwright codegen https://www.saucedemo.com
A failure that only happened in CI Trace Viewer Download the trace artifact and open it
Watching slowly Slow motion use: { launchOptions: { slowMo: 500 } }

The VS Code extension combines several of these: run a single test, set breakpoints and pick locators from the editor.

page.pause() and the Inspector

page.pause() is the pause button: execution stops and the Playwright Inspector opens, where you can step over actions, try locators live and resume. Remove it before committing — in a headless CI run there's no Inspector to resume from.

Screenshots and Videos

Option Values Recommended
screenshot 'off', 'on', 'only-on-failure' 'only-on-failure'
video 'off', 'on', 'retain-on-failure', 'on-first-retry' 'retain-on-failure' or 'on-first-retry'

Screenshots, videos and traces are saved per test in test-results/ and appear in the HTML report. For a manual screenshot: await page.screenshot({ path: 'cart.png', fullPage: true }), or of one element: await locator.screenshot({ path: 'badge.png' }).

Debugging a CI-Only Failure

  1. Publish playwright-report/ and test-results/ as build artifacts (and the JUnit XML to the CI test view).
  2. Open the failing test in the HTML report — read the error and the failed step.
  3. Open its trace: compare the DOM snapshot at the failing step with what you expected.
  4. Check the Network tab in the trace for failed or slow API calls, and the Console for errors.
  5. Reproduce locally with the same browser, viewport and --headed or --ui.

Most CI-only failures turn out to be timing (fixed with web-first assertions — see Playwright Auto-Wait), test data, or environment differences.

Coming from Selenium, where you had to build screenshots and logging yourself? Compare the equivalents in the Selenium ⇄ Playwright ⇄ Cypress Translator.

From Real Projects

I've built my automation skills on Selenium with Java and TestNG, and that background maps well onto Playwright: page classes become page objects, TestNG groups and parallel runs become projects and workers, and explicit waits become auto-waiting and web-first assertions. If you're coming from Selenium too, focus on those differences first. Testing Testsigma — a platform where users write automated tests in plain English — meant thinking like its users, who are testers themselves. Open the trace for every flaky failure before changing the test.

FAQs

What reporters does Playwright support?

Built in: list, line, dot, HTML, JSON, JUnit and blob. Several can run at once, and third-party reporters such as Allure plug in the same way.

What is the Playwright Trace Viewer?

A tool that replays a recorded test run — actions, DOM snapshots, console, network and source — so you can see exactly why a test failed.

Which trace setting should I use in CI?

'on-first-retry' with retries enabled, or 'retain-on-failure' without retries. Avoid 'on' for full suites — it's heavy.

How do you open a trace?

npx playwright show-trace path/to/trace.zip, from the HTML report, or by dropping the file into trace.playwright.dev.

What is page.pause()?

A call that pauses the test and opens the Playwright Inspector for step-by-step debugging in headed mode.

--debug or UI mode?

UI mode (--ui) for writing and exploring tests with time-travel; --debug for stepping through a specific test in the Inspector.