How to Debug Playwright Test Failures with Trace Files
A Playwright test fails in CI. The log says expect(locator).toBeVisible() timed out. You have no idea what the page looked like when it failed, what network requests fired, or what console errors appeared. You spend 30 minutes reproducing locally. Sometimes you can’t reproduce it at all.
Playwright traces solve this. A trace file records everything that happened during a test — every DOM state, every network request, every console message, every screenshot. This post covers how to enable traces, read them, and use them to debug failures systematically.
What is a Playwright Trace File?
A Playwright trace file is a .trace.zip archive that records the complete execution history of a single test. The trace captures state at every action step — clicks, navigations, assertions, waits — creating a replayable timeline of the test.
A single trace.zip contains DOM snapshots (the full rendered page at each action step), network request and response bodies, console log messages, screenshots at each step plus failure screenshots, and a complete action timeline with durations. Trace files are typically 0.5–5 MB per test, depending on page complexity and test length — TraceLoom production data, March 2026.
Playwright traces matter because test failures without context waste engineering time. Teams without traces spend an average of 15–30 minutes per failure attempting local reproduction — ThoughtWorks Technology Radar, 2024. Traces eliminate the reproduction step entirely: you see exactly what the test saw.
How to Enable Playwright Traces
Enable traces in your playwright.config.ts:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
trace: 'on', // Record a trace for every test
},
});
The trace option supports several modes:
| Mode | Behavior | Storage Impact |
|---|---|---|
'on' | Record a trace for every test | Highest — full traces for all tests |
'retain-on-failure' | Record traces for all tests, keep only for failures | Moderate — full traces only for failures |
'on-first-retry' | Record trace only on the first retry of a failed test | Low — traces only for retried tests |
'off' | No traces | None |
For CI pipelines, 'on' gives you the most debugging data. The storage cost is minimal — 1,000 tests produce roughly 500 MB–5 GB of traces. On S3, that’s under $0.12/month in Standard storage — AWS S3 pricing, 2026.
For local development, 'retain-on-failure' is a reasonable default — you get traces when you need them without the overhead on every run.
How to Open and Navigate the Trace Viewer
After a test run with traces enabled, open a trace in Playwright’s built-in viewer:
npx playwright show-trace test-results/my-test/trace.zip
The trace viewer opens in your browser with four main panels:
Action timeline (top): A horizontal timeline showing every Playwright action — page.goto, locator.click, expect().toBeVisible, etc. Each action is a clickable step. Click a step to see the page state at that exact moment.
DOM snapshot (center): A rendered snapshot of the page at the selected action step. You can inspect the DOM, hover over elements to see selectors, and view the page exactly as Playwright saw it.
Network panel (bottom-left): Every HTTP request and response during the test, with timing, status codes, headers, and response bodies. Filter by request type to find API calls that returned unexpected data.
Console panel (bottom-right): All browser console messages — console.log, console.warn, console.error, and unhandled exceptions — timestamped relative to the action timeline.
How to Debug Common Playwright Failures Using Traces
Timeout Failures
Timeout failures are the most common Playwright failure mode. The test waits for an element that never appears, a network request that never completes, or a condition that never becomes true.
In the trace viewer:
- Find the failing action step in the timeline (it’s marked with a red X).
- Click the step before the failure to see the last known good page state.
- Inspect the DOM snapshot: Is the expected element missing? Is it present but hidden? Is it inside an iframe?
- Check the network panel: Did the API call that populates the element fail? Return unexpected data? Never fire?
- Check the console: Are there JavaScript errors that prevented the element from rendering?
Timeout failures almost always fall into one of three categories: the API returned an error or unexpected data, a JavaScript error prevented rendering, or the selector doesn’t match the actual DOM structure.
Flaky Tests (Pass Sometimes, Fail Sometimes)
Flaky tests are timing-dependent failures. The trace viewer shows you the exact timing that caused the failure.
In the trace viewer:
- Compare a passing trace to a failing trace. Look at the action durations — is the failing run slower at a specific step?
- Check network timing: Did an API call take 3 seconds in the failing run versus 200ms in the passing run? That’s your race condition.
- Look for animations or transitions: If the element is present but mid-animation, Playwright may click a different position than expected.
Common causes of flakiness visible in traces: API latency variation causing elements to render after the assertion timeout, page transitions that haven’t settled before the next action fires, and client-side state that depends on non-deterministic ordering.
Element Not Found Errors
When Playwright can’t find an element matching your selector, the trace shows you exactly what the DOM looks like at that moment.
In the trace viewer:
- Click the failing step.
- In the DOM snapshot, use the element inspector to search for the element you expected.
- Compare the actual selector attributes (class names, test IDs, text content) against what your test expects.
- Check if the page is in the expected state — sometimes the element exists on a different page or behind a modal.
How to Store and Access Traces in CI
Traces are most valuable in CI, where you can’t reproduce the exact environment locally. Three approaches for storing CI traces:
Approach 1: CI Artifacts
Upload traces as CI artifacts after the test run:
# GitHub Actions
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-traces
path: test-results/
retention-days: 30
Limitation: artifacts are tied to the CI run. Finding a specific test’s trace requires navigating the CI interface and downloading the full artifact.
Approach 2: S3 Upload
Upload traces to S3 with a structured key path:
aws s3 sync ./test-results/ s3://your-bucket/traces/run-$RUN_ID/
S3 gives you durable storage, lifecycle policies (auto-delete after 30 days), and direct URL access. You can link to specific traces from your test dashboard.
Approach 3: TraceLoom (Automatic)
TraceLoom captures traces automatically for every test. Each EC2 worker uploads trace.zip files to your S3 bucket as tests complete. The TraceLoom dashboard links directly to each test’s trace — click a failed test and the trace viewer opens immediately, showing the full action timeline, DOM snapshots, and network activity.
No CI artifact configuration, no manual S3 uploads, no searching through zip files. Every test, every run, every trace — indexed and accessible from the dashboard.
Trace Analysis Best Practices
Always check the step before the failure. The failing step tells you what went wrong. The step before tells you why. If a click fails because the button isn’t visible, the previous step’s DOM snapshot shows what is visible instead.
Compare network timing across runs. For flaky tests, export traces from a passing and failing run. The network panel often reveals the timing difference — a slow API response, a missing preflight request, or a redirect that adds latency.
Use trace filtering for large suites. With trace: 'retain-on-failure', you only get traces for failures — which are the traces you actually need. For suites over 500 tests, this reduces storage and noise significantly while preserving debugging capability.
Treat traces as the primary debugging artifact. Logs tell you what happened. Traces show you. For Playwright test failures, a trace is more informative than any amount of console.log statements because it captures the complete page state, not just the values you thought to log.
Bottom line: Playwright traces eliminate the guesswork from test failure debugging. Enable trace: 'on' in CI, store the resulting .trace.zip files in S3 or a trace management platform, and use the trace viewer to see exactly what the test saw at every step. TraceLoom automates the entire pipeline — trace capture, storage, and dashboard integration — so every test failure comes with full context.
Related reading:
- How to Run Playwright Tests in Parallel on AWS Spot Instances — architecture for distributed test execution with trace capture at scale.
- What is BYOC Testing? — learn how BYOC keeps your traces inside your AWS account.
- TraceLoom Documentation — setup guides, configuration, and trace viewer integration.
Last updated: April 2026