Traces and Debugging CI Failures
A trace records every action, request, console message and DOM snapshot of a run — the single artefact that turns an unreproducible CI failure into a five-minute diagnosis.
3 min read · updated 19 September 2026
A trace is a recording of everything a test did: actions, network, console, and a DOM snapshot at each step. It is the reason a Playwright failure in CI is usually diagnosable in five minutes rather than an afternoon.
If you configure one thing from this section, configure this.
// playwright.config.ts
use: {
trace: 'on-first-retry'
}Green runs cost nothing. A failure produces a trace.zip that contains
enough to answer almost any question about what happened.
#Opening one
npx playwright show-trace trace.zipOr drag the zip onto trace.playwright.dev, which runs entirely client-side — nothing is uploaded, which matters if the trace contains session tokens.
#What it answers
The panels correspond to the questions people actually ask when a test fails:
"What was on screen?" — Every action has a DOM snapshot before and after. Not a picture: the real DOM, inspectable with developer tools. You can hover an element and see whether it was there, whether it was disabled, and what its computed attributes were.
"Why did it time out?" — The action log shows the locator it was waiting for and what it found. Zero elements, two elements, one element that was not visible — each is a different bug and the log names which.
"Did a request fail?" — The network tab lists every request with status, timing, headers and body. The most common "mysterious" browser failure is a 500 that the UI swallowed, and this is where it appears.
"Was there a JavaScript error?" — The console tab. An uncaught exception that did not break the assertion but did break the page.
"How long did each step take?" — The timeline. A step that normally takes 40ms and took 4 seconds is the finding.
#A worked diagnosis
A test fails in CI with:
TimeoutError: locator.click: Timeout 30000ms exceeded.
waiting for getByRole('button', { name: 'Pay £27.95' })Open the trace:
- Action log. The click waited 30s and found zero matching elements.
- DOM snapshot at that moment. There is a pay button — but its label reads "Pay £0.00".
- Network tab.
GET /api/basketreturned 200 with{ "lines": [] }. - Console. Nothing.
Diagnosis: the basket was empty, so the total was zero and the button's accessible name did not match. The bug is in the test's setup — the fixture created the basket for a different session — not in the checkout page.
That took about two minutes and no reproduction. Without the trace it is a timeout message and a guess.
#Tracing outside a failure
// Manual control, when you want a trace of a specific section.
await context.tracing.start({ screenshots: true, snapshots: true, sources: true });
// ... the interesting part ...
await context.tracing.stop({ path: 'trace.zip' });// Chunks: one trace per test in a shared context.
await context.tracing.startChunk({ title: test.info().title });
// ...
await context.tracing.stopChunk({ path: `traces/${test.info().title}.zip` });#In CI
- run: npx playwright test
- uses: actions/upload-artifact@v4
if: always() # the trace is needed precisely when it failed
with:
name: traces-${{ matrix.shard }}
path: test-results/
retention-days: 7if: always() rather than if: failure() if you also want the traces from
a run that was cancelled — a cancelled run often has the most interesting
hang.
#What other tools offer
| Tool | Equivalent |
|---|---|
| Playwright | Trace Viewer — the most complete |
| Cypress | time-travel command log with DOM snapshots; very good interactively, less portable |
| Selenium | BiDi logs and CDP capture, assembled yourself |
| Appium | server logs plus a page-source dump; no unified artefact |
Cypress's in-runner experience is arguably nicer than Playwright's while you are watching; Playwright's wins for CI because the artefact is a portable file you can open later on another machine.
#Debugging locally
npx playwright test --debug # inspector, step through
npx playwright test --ui # watch mode with a built-in trace view
PWDEBUG=console npx playwright test # browser open with playwright helpers
npx playwright codegen https://localhost:3000 # generate selectors by clickingThe UI mode is the one to reach for day to day: it runs tests, shows the trace live, and lets you re-run a single test against a paused browser.
#The habit worth building
When a test fails in CI, open the trace before you try to reproduce it locally. Local reproduction of a CI failure is often impossible — different timing, different data, different machine — and the trace frequently contains the answer outright.
The teams that find flakiness manageable are almost always the ones who do this.
Common questions
- What is in a Playwright trace?
- Every action with its duration and result, a DOM snapshot before and after each one, all network requests with headers and bodies, console messages, the test source with the failing line highlighted, and a screencast filmstrip. It is enough to diagnose most failures without reproducing them.
- Does tracing slow the tests down?
- Yes, noticeably — which is why trace on-first-retry is the standard setting. Green runs pay nothing, and the trace exists exactly when a test was behaving unpredictably.
- Can I open a trace without installing anything?
- Yes. trace.playwright.dev runs entirely in the browser and does not upload the file anywhere. Drag the zip in and it opens.
Runnable samples for this page
last test results ↗- TypeScript (Playwright)
browser/tests/diagnostics/trace-viewer
Working tests, not fragments — they run in CI on every push to 8exgh/endtoendtester-samples.
Was this page useful?
Related topics
- ScreenshotsCapturing the screen at the moment of failure, and using screenshot comparison as visual regression testing — configuration, masking and the flakiness to design out.
- Screen RecordingsVideo of a test run — when it is worth the storage, how to configure it so it costs nothing on green runs, and why a trace is usually better.
- Flaky TestsWhy tests fail intermittently, the six root causes and how to fix each one, how to detect flakiness deliberately, and what to do with a test you cannot fix today.
- PlaywrightThe default browser automation tool in 2026 — auto-waiting locators, tracing, sharding and fixtures — with the configuration that matters and the mistakes that still cause flakiness.
- Testing in GitHub ActionsA complete pipeline — unit tests, integration with containers, sharded Playwright, coverage and artefacts — plus the caching and concurrency settings that make it fast.
- Test ReportingGetting results out of the runner and in front of people — JUnit XML, pull request annotations, per-test history, and the numbers worth publishing.
- Browser TestingWhat a browser test can prove that nothing below it can, the three engines that matter, headless versus headed, and the cost model that should shape your suite.
- End-to-End TestingWhat belongs in an end-to-end suite and what does not, how many journeys are enough, and the practices that keep a browser suite from becoming the thing everyone ignores.