📖 The Story: The CI Ghost

David was losing his mind. A test named "Checkout Flow" was failing in GitHub Actions. The CI logs simply said: TimeoutError: Locator expected to be visible.

David ran the test locally. It passed. He ran it 50 times locally. It passed 50 times. He pushed a "fix" that just increased the timeout. CI failed again the next day.

Then he remembered Playwright Traces. He added trace: 'retain-on-failure' to his config. The next CI failure produced a trace.zip file. David downloaded it and ran npx playwright show-trace trace.zip.

A local web server popped up. He could see a timeline of every action. He clicked on the failed step. On the left, the DOM snapshot *before* the click. On the right, the DOM snapshot *after*. He suddenly saw it: a promotional pop-up was appearing over the checkout button for exactly 500 milliseconds, blocking the click. It only triggered on CI because the CI server was slightly slower at rendering the header.

He added a line to dismiss the pop-up. The test passed 100 times in CI. The ghost was gone.

Logs tell you what failed. Traces tell you why.

🎯 Why Trace Viewer?

Time Travel

Hover over the timeline to see the exact state of the DOM at every millisecond of the test.

📸

Snapshots

Automatic before/after screenshots for every single action without writing extra code.

🌐

Network Waterfall

See every API call, its payload, response, and timing.

💻

Console & Errors

All browser console logs and JavaScript errors captured perfectly in context.

🌍 Real World Example

Imagine a test that adds an item to a cart, but the "Add to Cart" API fails intermittently. The UI test sees a spinner forever. Without traces, you just see "Timeout on View Cart button." With traces, you open the Network tab, see the POST request, and notice it returned a 500 Internal Server Error. You've just diagnosed a backend bug using a frontend test.

🧒 Explain Like I'm 10

Imagine a plane crashes. Investigators don't just look at the wreckage; they look for the "Black Box." The Black Box records everything the pilots said and everything the plane's sensors felt right up until the crash.

Playwright's Trace Viewer is the Black Box for your test. When the test "crashes" (fails), you open the Black Box and listen to exactly what the browser was "saying" and "seeing" right before it broke.

🎓 Professional Explanation

Trace Viewer is a local Progressive Web App (PWA) generated by the Playwright test runner. When enabled, Playwright instruments the browser to record a highly compressed timeline of events. This includes DOM mutations (via a snapshot diffing algorithm), network traffic via CDP, console output, and Playwright action metadata.

The trace is saved as a .zip archive. You can open it via the Playwright CLI, which spins up a local HTTP server to render the interactive timeline UI.

📊 The Trace Timeline

What a Trace File Captures

1. page.goto() Network: GET /checkout -> 200 OK (120ms)
2. Click 'Add Item' Actionability checks passed. DOM snapshot saved.
3. Network Request POST /api/cart -> 500 Internal Server Error
4. expect(locator).toBeVisible() TimeoutError: Locator not visible after 5000ms

⚙️ Enabling Traces

You configure tracing in playwright.config.ts. You should NOT run traces on every test, as it slows down execution.

typescript · playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    /* Options: 'off', 'on', 'retain-on-failure', 'on-first-retry', 'on-all-retries' */
    trace: 'retain-on-failure' 
  }
});

Trace Options Breakdown:

  • 'on': Records a trace for every test. Very slow. Only use for local debugging.
  • 'retain-on-failure': Records a trace for every test, but deletes it if the test passes. Perfect for CI.
  • 'on-first-retry': Only records a trace if the test fails and is retrying. Excellent for flaky tests.

Running via CLI

bash
# Force tracing for a local debug run
npx playwright test --trace=on

👁️ Viewing the Trace

When a test fails in CI, Playwright outputs a link to download the trace. Once you have the .zip file:

bash
# Opens an interactive local web app
npx playwright show-trace trace.zip

Alternative: You can also drag and drop the .zip file directly into the hosted web app at https://trace.playwright.dev. This is entirely client-side; your trace data is not uploaded to any server.

🔍 Exploring the Trace UI

  • Timeline (Top): A waterfall of every action, network request, and browser event. Colors indicate type (green=action, blue=network, red=error).
  • Actions (Left Panel): A list of every Playwright command executed. Click one to jump to that moment.
  • Snapshots (Center): The actual browser UI. Hover over the timeline to "scrub" through the DOM like a video. Highlight elements to inspect their locators.
  • Source (Right Panel): The exact line of TypeScript/JavaScript code that was executing at that moment.
  • Console & Network (Bottom): Tabs to view all console logs and the complete network waterfall (similar to Chrome DevTools).

⚠️ Common Mistakes

Mistake 1: Tracing 'on' in CI

typescript · ❌ Slow CI
// ❌ BAD: Tracing every test slows down CI drastically
trace: 'on'

// ✅ GOOD: Only trace failures
trace: 'retain-on-failure'

Mistake 2: Ignoring the "Before" Snapshot

When an action fails, engineers often look at the "After" snapshot (the error state). The real clue is usually in the "Before" snapshot—what did the screen look like the millisecond *before* Playwright tried to click?

✅ Best Practices

  1. Use 'retain-on-failure' in CI. It gives you the diagnostic power without slowing down passing tests.
  2. Always download traces from CI. Set up your CI to upload the test-results/ folder as an artifact.
  3. Scrub the timeline. Don't just click through actions. Hover your mouse across the timeline to see subtle UI changes (like spinners or overlays).
  4. Check the Console. 90% of frontend bugs print a warning or error to the console. The Trace captures all of it.
💡 Pro Tip

In the Trace Viewer Snapshots view, click the "Eye" icon to reveal the locator Playwright was targeting. You will visually see a highlighted box over the element. If the box is over the wrong element, your locator is bad!

⚡ Performance Tips

  • Trace files are surprisingly small. Playwright uses a highly optimized format. A 30-second test with heavy network usage usually results in a 1-3 MB zip file.
  • Clean up old traces. In CI, don't keep trace artifacts for more than 7 days to save cloud storage.
  • Avoid console.log for large objects. If you console.log a massive JSON object, it gets recorded in the trace and bloats the file size.

🏗️ Senior Engineer Deep Dive

How Trace Data is Captured

Playwright uses the Chrome DevTools Protocol (CDP) to hook into the browser. For DOM snapshots, it doesn't save a full HTML document for every frame. Instead, it takes an initial snapshot and then records DOM mutations (via DOM.setChildNodes and similar events). When you view the trace, the UI reconstructs the DOM at any given timestamp by replaying those mutations. This is why the file size remains small despite recording thousands of frames.

Trace vs. Video vs. Screenshots

Screenshots capture a single moment. Video captures a visual timeline but lacks data (you can't see network calls or code). Traces capture everything: visual, network, code, and console. If you have traces, you generally don't need videos.

💼 Interview Questions

Beginner
How do you debug a test that only fails in CI?
Show Answer
I configure Playwright with trace: 'retain-on-failure'. When the test fails in CI, the trace.zip file is saved. I download it and run npx playwright show-trace trace.zip to inspect the timeline, DOM snapshots, and network calls to see exactly what went wrong.
Intermediate
What is the difference between 'retain-on-failure' and 'on-first-retry'?
Show Answer
'retain-on-failure' records a trace for every run but deletes it if the test passes. 'on-first-retry' does not record a trace on the first attempt; it only starts recording if the test fails and is automatically retried by the runner.
Advanced
What data is included in a Playwright trace file?
Show Answer
A trace includes DOM snapshots (before/after actions), network requests and responses, console logs, standard output, Playwright action metadata (locators, timings), and a mapping to the source code lines executing at each step.
Scenario
A test fails because a button click doesn't trigger a navigation. The UI looks fine. How do you use Trace Viewer to find the root cause?
Show Answer
I open the trace and go to the specific click action. First, I check the Console tab to see if a JavaScript error was thrown when clicking. Then, I check the Network tab to see if an API request was made. If no network request was made, the frontend JS is broken. If a request was made but returned a 500, the backend is broken. The Trace isolates the issue perfectly.

🏋️ Practical Exercise

🎯 Hands-On Practice Easy

Generate and Explore a Trace

  1. Run a test locally with tracing forced on: npx playwright test --trace=on
  2. When the test finishes, click the generated URL in the terminal, or run npx playwright show-trace on the output file.
  3. Hover your mouse over the Timeline at the top.
  4. Watch the DOM snapshot change in the center.
  5. Click on a network request in the bottom panel and inspect its JSON response.

🚀 Mini Project

🏗️ The Intentional Bug

  1. Write a test that navigates to a site.
  2. Add a line of code that intentionally targets a non-existent element (e.g., await page.getByRole('button', { name: 'DoesNotExist' }).click();).
  3. Run with --trace=on.
  4. Open the trace. Go to the failed step.
  5. Use the "Pick Locator" tool in the Trace UI to find a locator for an element that *does* exist on the page.

📝 Quiz

Test your understanding. Click an option to check your answer.

1. Which CLI command opens a trace file?
A) npx playwright open-trace trace.zip
B) npx playwright show-trace trace.zip
C) npx playwright trace trace.zip
D) npx playwright debug trace.zip
Answer: B — npx playwright show-trace spins up a local server to render the trace UI.
2. What is the recommended trace setting for CI pipelines?
A) 'on'
B) 'off'
C) 'retain-on-failure'
D) 'always'
Answer: C — 'retain-on-failure' ensures you have traces for debugging without slowing down passing tests.
3. What can you NOT see in the Playwright Trace Viewer?
A) DOM snapshots before and after an action
B) Network requests and responses
C) Backend database query execution times
D) Console logs
Answer: C — Trace Viewer is a frontend/browser tool. It cannot see inside your backend database.
4. How does hovering over the Trace Timeline help?
A) It downloads the trace.
B) It scrubs through the DOM state, showing the page at that exact millisecond.
C) It deletes network logs.
D) It highlights broken code.
Answer: B — Hovering over the timeline updates the center Snapshots panel, allowing you to "time travel" through the UI.
5. Why should you avoid setting trace to 'on' for all CI tests?
A) It requires a paid license.
B) It significantly slows down test execution.
C) It overrides parallelism.
D) It corrupts the HTML report.
Answer: B — Tracing adds overhead. Running it for every test, including passing ones, doubles or triples suite execution time.
6. If you have trace.zip, do you still need video recordings?
A) Yes, traces do not contain visual data.
B) No, traces include DOM snapshots which are better than video.
C) Yes, videos are required for CI.
D) Only for mobile tests.
Answer: B — Traces reconstruct the UI visually via DOM snapshots, making heavy video files largely unnecessary.
7. What does the "Source" panel in the Trace UI show?
A) The website's HTML source code.
B) The Playwright framework source code.
C) The exact line of your test script (e.g., spec.ts) executing at that moment.
D) The Node.js internal logs.
Answer: C — It maps the action back to your TypeScript/JavaScript test file, showing the exact line of code being executed.
8. Where can you view a trace file?
A) Only in VS Code.
B) Only in GitHub Actions UI.
C) Via the local CLI or by dragging it into trace.playwright.dev.
D) Only on a Linux machine.
Answer: C — You can use the local CLI server or the public web app, which processes the file entirely in your browser.
9. How does Playwright keep trace file sizes small?
A) By compressing the zip file heavily.
B) By taking an initial DOM snapshot and recording only subsequent mutations.
C) By limiting network logs to 10 requests.
D) By downscaling images.
Answer: B — It uses a mutation-diffing algorithm rather than saving full-page HTML for every frame.
10. What is the "Eye" icon used for in the Snapshots panel?
A) To close the trace viewer.
B) To reveal the locator Playwright was targeting on that element.
C) To take a screenshot.
D) To change dark mode.
Answer: B — It highlights the element Playwright interacted with, helping you debug bad locators visually.

❓ FAQ

Q: Are trace files secure to upload to cloud tools?

A: Trace files contain DOM snapshots and network payloads. If those contain sensitive PII or secrets, do not upload them to public tools. trace.playwright.dev processes everything client-side and doesn't upload data, but always verify your company policy.

Q: Can I view traces on my mobile phone?

A: Technically yes, via the web app, but the UI is heavily optimized for desktop screens with multiple panels.

Q: Does tracing work with sharded tests?

A: Yes. Each shard generates its own trace files for failed tests. You just need to ensure your CI uploads artifacts from all shard jobs.

📦 Summary

🎯 Key Takeaways

  • Trace Viewer is the ultimate debugging tool for flaky CI tests.
  • Use 'retain-on-failure' in CI to balance speed and diagnostics.
  • Traces contain DOM snapshots, network, console, and source code.
  • Hover over the timeline to time-travel through the DOM.
  • Open traces via CLI or drag-and-drop into the web app.
  • Always check the "Before" snapshot to see what blocked the action.