advanced20 min

Trace Viewer, Screenshots, Video, and Debugging

The diagnostic artifacts Playwright can capture around a failure, and Playwright Inspector's step-through debugging — reconstructing exactly what happened without re-running blind.

What you'll learn

  • Explain what a Playwright trace captures that a screenshot alone does not
  • Choose the correct artifact-capture setting (screenshot, video, trace) for a given diagnostic need
  • Use Playwright Inspector's step-through mode to diagnose a failing test locally

Prerequisites

Explanation

A screenshot captures one still frame — the page's appearance at one instant, either on failure (screenshot: "only-on-failure") or at every step. A video captures continuous playback of the whole test. A trace (trace: "on-first-retry" or "retain-on-failure") captures something categorically richer than either: a full, replayable timeline of the test — every action, every network request/response, DOM snapshots at each step, and console output — viewable afterward in Trace Viewer, a tool that lets you scrub through the test's exact execution step by step, inspecting the real DOM state and real network activity at any point, long after the run finished. A trace answers "what actually happened, in what order, with what data" in a way a single still image or a video (which shows appearance but not the underlying DOM/network state) cannot.

The practical capture-setting decision: screenshots are cheap and always worth keeping on failure at minimum; video adds real value for genuinely visual, timing-sensitive issues (an animation, a layout shift) where seeing continuous motion matters; trace is the most expensive to store but by far the most diagnostically complete, which is why the common, sensible default is trace: "on-first-retry" — capture a trace only when a test has already failed once and is being retried, so the (relatively expensive) trace exists specifically for the runs that actually need deep diagnosis, not for every single passing test.

Playwright Inspector (npx playwright test --debug, or await page.pause() inside a test) opens a real, interactive browser window alongside a step-through control panel: you can step through actions one at a time, inspect the live page, and even generate a locator by clicking an element directly in the paused browser. This is fundamentally different from "add a bunch of console.log calls and re-run repeatedly" — Inspector lets you pause at the exact moment something is wrong and interact with the real, live page state at that instant, rather than reconstructing what must have happened from scattered log output after the fact.

Example

Modeling the capture-setting decision (screenshot vs video vs trace) and Trace Viewer's step-by-step replay concept as data.

function recommendCaptureSetting(diagnosticNeed) {
  const recommendations = {
    "quick-visual-check": "screenshot",
    "animation-or-layout-shift": "video",
    "full-reconstruction-of-what-happened": "trace",
  };
  return recommendations[diagnosticNeed] ?? "screenshot"; // screenshot is the safe, cheap default
}
console.log(recommendCaptureSetting("full-reconstruction-of-what-happened")); // "trace"

// A simplified model of Trace Viewer's step-through concept: a recorded list of steps
// you can move through independently, inspecting state at any point.
class FakeTrace {
  constructor(steps) { this.steps = steps; this.index = 0; }
  stepForward() { if (this.index < this.steps.length - 1) this.index++; return this.steps[this.index]; }
  stepBackward() { if (this.index > 0) this.index--; return this.steps[this.index]; }
  current() { return this.steps[this.index]; }
}
const trace = new FakeTrace(["goto /login", "fill username", "click Sign in", "assertion failed"]);
trace.stepForward(); trace.stepForward();
console.log(trace.current()); // "click Sign in" -- you can inspect state at THIS exact step, not just the final failure

Try it yourself

Step the trace forward one more time to reach 'assertion failed', then step backward twice and confirm you land back on 'fill username'.

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Guided exercise

Guided exercise

Write recommendCaptureSetting(diagnosticNeed) mapping 'quick-visual-check' -> 'screenshot', 'animation-or-layout-shift' -> 'video', 'full-reconstruction-of-what-happened' -> 'trace'. Default to 'screenshot' for anything unrecognized.

Checks: recommends trace for full reconstruction needs · recommends video for animation/timing issues · defaults to screenshot for an unrecognized need

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Independent exercise

Independent exercise

Write findStepBeforeFailure(steps, failureStepName) that returns the step immediately BEFORE the named failure step in the steps array (or null if the failure step is first, or not found at all) -- modeling exactly the Trace Viewer workflow of stepping backward from a failure to see what state led to it.

Checks: finds the step immediately preceding the named failure · returns null when the failure is the first step · returns null when the failure step isn't found at all

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Common mistakes

  • Enabling full trace capture on every single test run, including passing ones -- traces are the most storage-expensive artifact; 'on-first-retry' captures them specifically for runs that actually need deep diagnosis.
  • Relying only on a single failure screenshot when the actual question is 'what led up to this,' not just 'what did it look like at the end' -- a screenshot alone can't show the sequence of actions or network activity that produced that final state; a trace can.
  • Debugging purely by adding console.log statements and re-running repeatedly, instead of using Playwright Inspector to pause at the exact failure point and interact with the real, live page state directly.

Knowledge check

Knowledge check

1. What does a Playwright trace capture that a single failure screenshot does not?
2. Why is `trace: "on-first-retry"` a sensible common default, rather than capturing a trace on every test run?
3. How does debugging with Playwright Inspector (--debug or page.pause()) fundamentally differ from adding console.log statements and re-running?

Takeaway

A trace is a complete, replayable execution record — richer than a screenshot or video — and capturing it selectively (on-first-retry) targets its real cost at the runs that need deep diagnosis; Playwright Inspector lets you pause and interact with the real, live page at the moment of failure, a fundamentally more direct tool than scattered logging.

Summary

Screenshots capture one moment; video captures continuous playback; a trace captures a full, replayable timeline (actions, network, DOM snapshots, console) viewable in Trace Viewer. trace: 'on-first-retry' targets this expensive artifact at runs that need it. Playwright Inspector (--debug, page.pause()) enables live, step-through debugging against the real page.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.