skip to content

In Playwright, what do tracing's screenshots, snapshots and sources options each capture?

level: middleimportance: should knowfreq 45%

answer

  1. Three streams, not one artefact
  2. One is pixels, one is structure
  3. One copies code rather than page state
  4. Trim the cheapest to rebuild first

basics

~20 s

Screenshots capture image frames of the page over time, snapshots capture the DOM around each action so the page can be re-rendered, and sources copies the test files that drove the run into the zip.

solid answer

~40 s

`context.tracing.start({ screenshots: true, snapshots: true, sources: true })` controls what goes inside the zip. **Screenshots** record image frames as the page changes, giving the trace a filmstrip along its timeline. **Snapshots** record the DOM plus its styles before and after each action, which is what makes a captured page inspectable rather than just a picture. **Sources** copies the test's own source files into the archive so the code that ran travels with the evidence — useful when the zip is opened on a machine that does not have the repository. Each one costs size and capture time, so trimming `sources`, then `screenshots`, is the usual way to shrink traces. The same three flags are available in the runner's object form of the option: `trace: { mode: 'retain-on-failure', sources: false }`.

code

typescript · 13 lines
typescript
const context = await browser.newContext();
await context.tracing.start({
  title: 'order tracker: checkout to delivery',
  screenshots: true,
  snapshots: true,
  sources: true,
});

const page = await context.newPage();
await page.goto('https://orders.example.com/track/9182');
await page.getByRole('button', { name: 'Refresh status' }).click();

await context.tracing.stop({ path: 'traces/order-flow.zip' });

go deeper

for a junior

Learn the three names and what each one puts in the zip. The one to keep straight is that snapshots store page structure while screenshots store pictures.

for a middle

Explain why the two visual streams differ in kind and what each costs, and show that the same flags exist in the runner's object form of the trace option.

for a senior

Demonstrate a trimming order when artefacts are too large, and justify keeping snapshots last because they carry the state a diagnosis depends on.

for a principal

Own the default contents for the organisation's suites and the exceptions, balancing storage against how often a trace has to answer a question nobody can reproduce.

A trace zip is not one artefact but several streams recorded together, and the options on `context.tracing.start()` decide which streams are in it. The same names appear in the test runner's object form of the `trace` option, so the knowledge transfers both ways. ## The three content options - **`screenshots`** — periodic image frames of the page as it changes. These are what give a trace its filmstrip: a strip of thumbnails along the timeline showing what the order tracker looked like second by second while a driver marker moved. - **`snapshots`** — captures of the DOM and its styles taken around each action, before and after it. A snapshot is structured page state, not an image, which is why it can be inspected element by element rather than merely looked at. - **`sources`** — the test's own source files, copied into the zip so the archive can show the code beside the recorded actions even when it is opened somewhere the repository is not checked out. ## How they differ in kind | option | what is stored | biggest cost driver | |---|---|---| | `screenshots` | image frames over time | page visual churn, animations, long tests | | `snapshots` | DOM plus styles around each action | number of actions, size of the document | | `sources` | copies of test files | number of files the run touched | The first two are recorded *while the test runs* and grow with the test's behaviour. The third is a copy step and grows with the code, not the run. ## Where you set them In library code you pass them when you start tracing: ```ts await context.tracing.start({ title: 'checkout to delivery', screenshots: true, snapshots: true, sources: true, }); // ... drive the order tracker ... await context.tracing.stop({ path: 'traces/order-flow.zip' }); ``` With the test runner you do not call this yourself — the runner starts and stops tracing for the fixture context according to the `trace` option. To change the contents there, use the object form: 1. `trace: 'retain-on-failure'` — mode only, contents at their defaults. 2. `trace: { mode: 'retain-on-failure', sources: false }` — same mode, no copied test sources. 3. `trace: { mode: 'on', screenshots: false, snapshots: true }` — record everything, but keep only the inspectable page state. ## Two more options worth knowing - **`title`** — a human label for the recording, so a folder of zips is distinguishable without opening each one. - **`name`** — a file-name prefix for the trace, used when the trace is written into the output directory rather than an explicit path. Both are accepted by `context.tracing.start()` and by `context.tracing.startChunk()`. ## Trimming a trace that is too big When zips are too large to keep or upload, cut in this order: - Turn off `sources` first — it is the stream you can most easily reconstruct from the repository. - Turn off `screenshots` next if the failure is structural rather than visual; you lose the filmstrip but keep the page state. - Leave `snapshots` on for as long as you can. Without them a trace degrades into a list of action names and a few pictures, which is rarely enough to diagnose anything. - Only then reconsider the mode itself, so that fewer attempts are recorded at all. ## A common misconception Candidates often treat `screenshots` and `snapshots` as two words for the same thing. They are not: one is a raster image and cannot be queried, the other is page structure and can. A trace with `snapshots: false` looks superficially fine — there is still a timeline and a filmstrip — right up to the moment you want to know why a button was disabled, at which point there is nothing to inspect.

  • Why is snapshots: false a false economy in most suites?
    Because snapshots are the stream that makes a trace diagnostic. Without them you keep the action list and any image frames, but you cannot inspect the page as it stood — no element attributes, no computed styles, no explanation for why a control was disabled or a locator matched nothing. You have kept the cheapest parts and dropped the one that answers questions.
  • How would you set these contents when using the Playwright test runner rather than the library API?
    Use the object form of the trace option: `trace: { mode: 'retain-on-failure', sources: false }`. The runner owns starting and stopping tracing on the fixture context, so you never call the tracing API yourself; the object simply passes the same content flags through alongside the mode.

saying these in an interview costs you the question

  • Treats screenshots and snapshots as the same option
  • Thinks snapshots are images of the page
  • Believes the content options change which attempts are recorded
  • Disables snapshots first when shrinking a trace
  • Calls tracing.start manually while the runner manages tracing