Debugging September 21, 2026 15 min read

Playwright Trace Viewer Tutorial: Debug Tests Like a Pro (2026)

Trace Viewer is the most underused debugging tool in the Playwright ecosystem. It is a time-travel debugger that records every action, network request, DOM snapshot, and console log during test execution — and it reduces debugging time from 30–60 minutes to 5–10 minutes per flaky test. This complete 2026 tutorial shows you how to master it.

Flaky tests are the silent productivity killer of every QA team. You see a red CI pipeline, open the logs, stare at a cryptic timeout error, and spend the next hour sprinkling console.log statements across your test files. Sound familiar?

Playwright's Trace Viewer eliminates that entire cycle. It records a complete timeline of your test execution — every click, every network request, every DOM mutation — and lets you replay it in the browser like a flight recorder for your tests. No extra tools, no setup headaches. If you are still debugging with console.log in 2026, this guide will change your workflow permanently.


What Is Playwright Trace Viewer?

Playwright Trace Viewer is a time-travel debugger built directly into Playwright. When enabled, it records every action your test performs — navigations, clicks, form fills, assertions — along with the complete execution context at each step: DOM snapshots, network requests, console logs, and even the test source code.

After a test run, you open the trace file in your browser and get a visual timeline of the entire execution. You can click on any action and see:

  • The DOM before and after the action — exactly what the page looked like when that click or fill happened
  • Every network request that fired, with full headers, request body, and response
  • Console output at that exact moment in the timeline
  • Actionability checks — was the element visible? Was it enabled? Was it attached to the DOM?
  • The test source code with the current line highlighted

Think of it as Chrome DevTools, but for your entire test execution — frozen in time and fully navigable. You do not need to install anything extra. Trace Viewer opens in your default browser and works with any Playwright test written in TypeScript, JavaScript, Python, Java, or C#.

Key insight: Trace Viewer is not just for failed tests. Recording traces for passing tests helps you understand why a test works, catch slow steps before they become timeouts, and document test behavior for new team members.

Why Trace Viewer Beats console.log Debugging

Most developers debug Playwright tests the same way they debug application code: console.log everywhere. This works for simple cases, but it falls apart when you are dealing with flaky tests, race conditions, or failures that only happen in CI. Here is how the common debugging approaches compare:

Method What You See Limitations
console.log Variable values at specific points Blind to DOM state, noisy output, requires manual placement, no visual context
Screenshots Single frame of the page No context before/after, cannot inspect elements, one moment in time only
Video recording Pixel-level screen capture Slow to scrub, no DOM inspection, no network data, large file sizes
Trace Viewer Full timeline with DOM snapshots, network, console, source code Requires trace recording enabled (minimal overhead)

The difference is stark. With console.log, you are guessing what happened. With Trace Viewer, you are seeing what happened — the full context at every step. For flaky tests that fail intermittently, this is the difference between a 5-minute fix and a 60-minute investigation.

How to Enable Traces in Your Tests

There are three ways to enable trace recording in Playwright. Each serves a different use case. The right choice depends on whether you want traces always, only on failures, or only on retries.

Method 1: On First Retry (Recommended Default)

This is the recommended default for most teams. Traces are only recorded when a test fails and Playwright retries it. Zero overhead for passing tests.

playwright.config.ts — on-first-retry
import { defineConfig } from '@playwright/test';

export default defineConfig({
  retries: 2,
  use: {
    // Only record trace on first retry — zero overhead for passing tests
    trace: 'on-first-retry',
  },
});

Method 2: Always On (For CI)

Record traces for every test, every run. Use this in CI when you want full debugging context for every failure, including first-run failures that never retry.

playwright.config.ts — always on
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    // Record trace for every test — useful in CI for full context
    trace: 'on',
  },
});

Method 3: Retain on Failure (Keep Only What Matters)

Record traces for all tests, but only save the trace file when a test fails. This gives you first-failure traces without the retry requirement, while keeping your disk usage manageable.

playwright.config.ts — retain-on-failure
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    // Record all traces, save only for failures
    trace: 'retain-on-failure',
  },
});

Which should you choose? Start with on-first-retry for local development. Switch to retain-on-failure or on in your CI config where you want traces for every failure without relying on retries.

Recording Your First Trace

Let's record and view a trace step by step. Even if you have never used Trace Viewer before, you will be up and running in under two minutes.

Step 1: Run your tests with tracing enabled

You can enable tracing from the command line without modifying your config file:

Terminal
# Run all tests with trace recording
npx playwright test --trace on

# Run a specific test file with tracing
npx playwright test tests/login.spec.ts --trace on

Step 2: Open the trace file

After the test run completes, Playwright saves trace files in the test-results/ directory. Open the trace with:

Terminal
# Open a specific trace file
npx playwright show-trace test-results/login-test/trace.zip

# Or open the last test run's trace from the HTML report
npx playwright show-report

The Trace Viewer opens in your default browser. No installation required — it is a web application bundled with Playwright.

Step 3: Explore the trace

You will see a timeline of every action your test performed. Click on any action to see the DOM snapshot, network activity, and console output at that exact moment. You can also drag the timeline scrubber to navigate through the execution frame by frame.

Quick shortcut: You can also drag and drop any .zip trace file onto trace.playwright.dev to view it instantly in the browser — no local Playwright installation needed.

Anatomy of a Trace: What You See

The Trace Viewer UI is organized into panels, each showing a different dimension of your test execution. Understanding these panels is the key to fast debugging.

Timeline Bar

The top of the Trace Viewer shows a visual timeline of all actions. Each action appears as a colored segment — green for passed steps, red for failures. You can see at a glance where the test spent the most time and where it broke.

Actions Panel

The left sidebar lists every step your test performed: page.goto(), locator.click(), locator.fill(), expect() assertions. Each action shows its duration in milliseconds. Click any action to jump to that point in the timeline.

DOM Snapshot

This is the most powerful panel. For every action, Trace Viewer captures the before and after state of the DOM. You can inspect elements, check visibility, verify text content, and even see CSS computed styles — exactly as the page appeared when the action executed. This is what makes Trace Viewer a true time-travel debugger.

Network Tab

Every HTTP request and response is captured with full details: URL, method, status code, headers, request body, and response body. You can filter by request type (XHR, Fetch, Document, etc.) and see the exact timing of each request relative to your test actions.

Console Tab

All console.log, console.warn, and console.error output from the page is captured and timestamped. You can see exactly which console messages appeared at each point in the test timeline — no more guessing which log corresponds to which action.

Source Tab

The Source tab shows your test source code with the current line highlighted. As you click through actions in the timeline, the source highlight moves to the corresponding line. This makes it trivial to correlate test code with execution behavior.

Metadata

The metadata section shows the browser engine (Chromium, Firefox, WebKit), viewport dimensions, test file path, and test name. This is particularly useful when debugging cross-browser failures — you can immediately see which browser was used for a failing trace.

Debugging Flaky Tests with Trace Viewer

Flaky tests — tests that pass locally but fail intermittently in CI — are the number one debugging challenge for QA teams. Trace Viewer transforms flaky test debugging from a guessing game into a forensic investigation.

Real-world example: The intermittent login failure

Consider this common scenario: your login test passes 100% of the time on your machine but fails ~20% of the time in CI with a timeout error on the dashboard assertion.

TypeScript — the flaky test
test('user can log in and see dashboard', async ({ page }) => {
  await page.goto('/login');
  await page.getByLabel('Email').fill('user@example.com');
  await page.getByLabel('Password').fill('password123');
  await page.getByRole('button', { name: 'Sign In' }).click();
  // This line times out ~20% of the time in CI
  await expect(page.getByText('Welcome back')).toBeVisible();
});

With console.log, you would add logging before and after each step, push to CI, wait for the next failure, read the logs, and repeat. This cycle takes hours.

With Trace Viewer, you open the failing trace and immediately see:

  1. Actions panel: The click('Sign In') action completed successfully, but the expect(toBeVisible) action timed out after 30 seconds
  2. DOM snapshot (after click): The page shows a loading spinner instead of the dashboard — the API response has not arrived yet
  3. Network tab: The POST /api/auth/login request took 28 seconds to respond (vs 200ms locally). The CI server has higher latency to the API
  4. Console tab: A warning message reads "Slow network detected, retrying..."

The root cause is clear in 5 minutes: the CI environment has higher network latency, causing the API call to take longer than the default timeout. The fix is to increase the assertion timeout or add a waitForResponse before the assertion.

TypeScript — the fix
test('user can log in and see dashboard', async ({ page }) => {
  await page.goto('/login');
  await page.getByLabel('Email').fill('user@example.com');
  await page.getByLabel('Password').fill('password123');

  // Wait for the API response before asserting
  await Promise.all([
    page.waitForResponse(resp =>
      resp.url().includes('/api/auth/login') && resp.status() === 200
    ),
    page.getByRole('button', { name: 'Sign In' }).click(),
  ]);

  await expect(page.getByText('Welcome back')).toBeVisible();
});

Debugging stat: Teams using Trace Viewer report reducing flaky test debugging time from 30–60 minutes to 5–10 minutes per test. The DOM snapshots alone eliminate the most common blind spot: not knowing what the page actually looked like when the assertion ran.

Debugging Network Issues

The Network tab in Trace Viewer is essential for debugging API-dependent tests. Whether you are mocking API responses, intercepting network calls, or diagnosing CORS errors, the network panel gives you complete visibility.

Common network debugging scenarios

  • API mocking failures — Your route handler is not intercepting the right URL. The Network tab shows both the mocked requests and the ones that slipped through to the real server.
  • CORS issues — The request was blocked by CORS policy. You can see the preflight OPTIONS request and the missing headers in the response.
  • Slow responses — A request that usually takes 100ms took 5 seconds. The timing column shows exactly which requests are slow, so you can add targeted waitForResponse calls.
  • Failed requests — A 500 error from the API caused the page to show an error state instead of the expected content. The response body in the Network tab shows the exact server error message.

Filtering and inspecting requests

In the Network tab, you can filter requests by type (XHR, Fetch, Document, Stylesheet, Image), search by URL, and click any request to see the full details: headers, query parameters, request body, response body, and response time. This is the same information you would get from Chrome DevTools — but captured at the exact moment your test action executed.

TypeScript — debugging a mocked API
test('displays user list from API', async ({ page }) => {
  // Set up API mock
  await page.route('**/api/users', route => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify([
        { id: 1, name: 'Alice' },
        { id: 2, name: 'Bob' },
      ]),
    });
  });

  await page.goto('/users');

  // If this fails, check the Network tab in the trace:
  // - Did the route intercept the request?
  // - Was the URL pattern correct?
  // - Did the page make the request at all?
  await expect(page.getByText('Alice')).toBeVisible();
});

Advanced: Trace Viewer in CI/CD

Traces are most valuable in CI/CD where you cannot manually run tests with DevTools open. The key is to automatically save traces as build artifacts and make them easily accessible to the team.

GitHub Actions: Attach traces as artifacts

This workflow runs your Playwright tests and uploads trace files as GitHub Actions artifacts whenever tests fail. Any team member can download the traces directly from the PR.

YAML — .github/workflows/playwright.yml
name: Playwright Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      - name: Run Playwright tests
        run: npx playwright test
        env:
          CI: true

      - name: Upload trace artifacts
        # Upload traces only when tests fail
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-traces
          path: test-results/
          retention-days: 30

When a test fails in CI, the traces appear as downloadable artifacts in the GitHub Actions run. Click the artifact, download the zip, and open it with npx playwright show-trace — or drag it onto trace.playwright.dev.

Sharing traces with teammates

Trace files are self-contained .zip archives. You can share them via:

  • Slack/Teams — drop the zip file in a channel; teammates open it with npx playwright show-trace
  • trace.playwright.dev — drag-and-drop for instant browser-based viewing
  • Cloud storage — upload to S3/GCS and share a link; traces are small (typically 1–5MB)
  • PR comments — use a GitHub Action to automatically post trace links as PR comments on failure

Trace Viewer + Claude AI: AI-Powered Debugging

The future of test debugging is combining Trace Viewer's execution context with Claude AI's reasoning. Instead of manually interpreting traces, you can feed trace data to Claude and get instant analysis.

How it works

Export the trace's key data — the action list, network requests, console errors, and DOM snapshots — and provide it to Claude. Claude can read trace data via the Playwright MCP Server and suggest targeted fixes based on the full execution context.

Practical workflow:

  1. Run failing tests with tracing enablednpx playwright test --trace on
  2. Extract key data from the trace — action timeline, network failures, DOM diffs, console errors
  3. Provide context to Claude — paste the trace summary and ask Claude to diagnose the failure
  4. Get an AI-generated fix — Claude analyzes the race condition, missing wait, or wrong selector and produces a corrected test

This is not theoretical. Teams using Claude AI with Playwright trace data report fixing flaky tests 3–5x faster than manual analysis alone. The AI excels at spotting patterns across multiple trace files — identifying common failure modes that a human might miss when reviewing traces one at a time.

Learn this workflow: The complete course covers how to integrate Claude AI with Playwright debugging, including trace analysis, MCP Server connectivity, and AI-powered test healing.

Frequently Asked Questions

How do I open Playwright Trace Viewer?

Run npx playwright show-trace trace.zip in your terminal to open the Trace Viewer in your default browser. You can also open trace files directly at trace.playwright.dev by dragging and dropping the .zip file. No additional tools or installations are needed — Trace Viewer runs entirely in the browser.

Does Trace Viewer slow down my tests?

Trace recording adds approximately 5–10% overhead to test execution time. The recommended configuration is trace: 'on-first-retry', which only records traces when a test fails and retries — meaning zero overhead for passing tests. For CI pipelines, use retain-on-failure to keep traces only for failing tests without impacting overall suite speed.

Can I share traces with my team?

Yes. Trace files are portable .zip archives that anyone can open. Share them via Slack, email, or cloud storage. You can also upload traces to trace.playwright.dev for instant browser-based viewing — just share the URL. In CI/CD, attach traces as GitHub Actions artifacts so any team member can download and inspect them directly from the PR.

What's the difference between trace and video recording?

Video recording captures pixel-level screen recordings but offers no interactivity — you cannot inspect the DOM, view network requests, or check console logs. Trace Viewer captures the full execution context: DOM snapshots before and after every action, all network requests with headers and bodies, console output, and test source code mapping. Traces are significantly more useful for debugging than videos.

How do I enable traces only for failed tests?

Set trace: 'retain-on-failure' in your playwright.config.ts under the use section. This records traces for all tests but only saves the trace file when a test fails. Alternatively, use trace: 'on-first-retry' which only starts recording on the first retry attempt, meaning no trace overhead for tests that pass on the first run.


Asim Noaman - Playwright and Claude AI course instructor

Asim Noaman

Senior QA Automation Engineer & AI Testing Specialist

With years of hands-on experience building test automation frameworks for production applications, Asim specializes in combining traditional QA methodologies with cutting-edge AI tools. He has helped teams adopt Playwright and AI-driven testing workflows to ship faster with fewer bugs.

Udemy Instructor Published course author
Playwright + AI Expert Specialized in AI-powered QA
Production Experience Enterprise-grade frameworks
Connect on LinkedIn

Complete Course

Master Playwright Debugging — Trace Viewer & Beyond

Learn Trace Viewer, advanced debugging patterns, and AI-powered test analysis in the complete Udemy course. Go from zero to production-grade Playwright automation with real projects and hands-on labs.

  • Trace Viewer deep-dive
  • Flaky test debugging patterns
  • CI/CD trace integration
  • Claude AI-powered debugging
Enroll Now on Udemy →