skip to content

Video and Screenshots

Pictures and video of a run, taken by the runner on failure or by hand mid-test, and where they land. Asked to check you can tell evidence of a bug from a baseline you compare against.

on this pageshow

explore

questions

5

In Playwright Test, what does the screenshot: 'only-on-failure' option capture, and where does the file land?

level: juniorimportance: must knowfreq 76%

answer

  1. A config switch, not a test call
  2. Four values, one of them conditional
  3. Fires after the verdict, not at the assertion
  4. Lands beside the trace and the video
  5. Viewport only unless you ask otherwise

basics

~20 s

The runner itself photographs every page open in the test at the moment the test ends failed, and only then. Each PNG is written into that test's folder under outputDir, test-results by default, and attached to the result.

solid answer

~40 s

`screenshot` is a Playwright Test runner option set under `use`, not something a test calls. In Playwright 1.63 it takes `'off'`, `'on'`, `'only-on-failure'` or `'on-first-failure'`, plus an object form such as `{ mode: 'only-on-failure', fullPage: true }`. With `'only-on-failure'` the runner captures each open page after a test ends failed or timed out, writes `test-failed-1.png` (then `-2`, one per page) into the test's directory under `outputDir` (`test-results/` by default), and records it as an attachment named `screenshot` so the HTML report shows it inline. The capture is viewport-only unless you ask for `fullPage`, and it happens after the test body has finished, so it shows the aftermath of the failure rather than the instant of it. Per-test output folders are cleaned before the test runs, so images never leak across runs.

code

typescript · 8 lines
typescript
import { defineConfig } from '@playwright/test';

export default defineConfig({
  outputDir: 'test-results',
  use: {
    screenshot: { mode: 'only-on-failure', fullPage: true },
  },
});

go deeper

for a junior

Recall the four mode values and that this is config, set under use, not a call inside a test. Know the file lands in the test's folder under outputDir, test-results by default.

for a middle

Explain the timing: capture happens after the test body ends, one image per open page, viewport only unless fullPage is set, and the file is attached to the result so reporters can show it.

for a senior

Show judgment about cost and noise: only-on-failure versus on-first-failure on a flaky suite, fullPage on long pages, and knowing when a screenshot is too late and a trace is the right evidence.

for a principal

Own the evidence budget across projects: which suites get images at all, how retries multiply artefacts, and how config scoping expresses that policy instead of ad-hoc captures scattered through tests.

## What the option actually is `screenshot` is a **Playwright Test runner option**, not a page API. You set it under `use` in `playwright.config.ts`, or narrow it with `test.use({ screenshot: 'only-on-failure' })` inside a file or a `describe` block. When it is on, the runner takes the picture itself around the end of a test; your test code calls nothing. That is the whole point: evidence you did not have to remember to capture, on the runs where you were not watching. Its manual counterpart, `page.screenshot()`, is a separate mechanism you drive yourself mid-test. The two coexist happily, and most mature suites use both. ## The four modes In Playwright 1.63 the option accepts four string values: | Value | When the runner captures | Why you would pick it | |---|---|---| | `'off'` | never | the default; nothing is written | | `'on'` | at the end of every test, pass or fail | short smoke suites where you want a picture of every result | | `'only-on-failure'` | when a test ends failed or timed out | the usual CI setting: evidence exactly where it matters | | `'on-first-failure'` | on the first failing attempt only, not on later retries | stops a retried flaky test writing near-identical images | `'only-on-failure'` fires on **every** failed attempt, so a test that fails three times leaves three sets of images; `'on-first-failure'` leaves one. ## Which pages get captured, and when The runner captures each page open in the test, so an order-tracker test that opened the customer page plus a driver-detail popup produces two files, `test-failed-1.png` and `test-failed-2.png`. The timing matters more than people expect. Capture happens **after the test body has ended**, which means: - a toast that had already faded is not in the image; - a page you closed in a cleanup step cannot be photographed at all; - an element that only appeared while an action was in flight is long gone. The screenshot shows the *aftermath* of the failure, not the moment of it. For the moment itself you want a recorded trace or your own capture taken at the point you care about. ## Where the file lands 1. The runner picks a directory for the test inside **`outputDir`** (`test-results/` unless the config changes it), named from the spec file, the test title and the project, with a `-retry1` suffix on a retried attempt so attempts never overwrite each other. 2. It writes `test-failed-1.png` there, numbering upwards for each additional page. 3. It records the file as an **attachment** named `screenshot` on the test result, which is how the HTML report and other reporters render it inline instead of making a reader dig through folders. A test's output folder is cleaned before that test runs, so you never inherit an image from an earlier run; equally, anything you write outside `outputDir` is yours to manage. ## The object form The string form is shorthand for an object: ```ts use: { screenshot: { mode: 'only-on-failure', fullPage: true }, } ``` - `mode` -- one of the four values above. - `fullPage` -- capture the whole scrollable document instead of the viewport. The default is viewport-only, which on a long delivery-tracking page can crop away the driver map and the timeline, leaving you a photograph of a header. - `omitBackground` -- capture with a transparent background where the page paints none. ## What it is not - **Not a baseline.** These images are evidence of what happened; checking an image against an approved reference is a different mechanism with its own storage and approval flow. - **Not a replacement for a recorded trace.** One PNG of the end state is far less than a step-by-step recording; screenshots are the thing a human glances at first, not the whole story. - **Not free on `'on'`.** A full-page capture on every passing test buys wall-clock time and CI disk for images nobody opens. - **Not per-test selective on its own.** The mode applies to whatever scope you set it in; deciding which cases deserve which evidence is a policy call you express through config scoping. ## A sane default For a food-delivery order tracker, `'only-on-failure'` with `fullPage: true` in the shared config pays for itself: green runs write nothing, and a red one hands the reviewer the entire page -- status banner, driver map and footer -- without anyone editing a test.

  • How does 'on-first-failure' behave differently from 'only-on-failure' on a test that fails three times?
    `'only-on-failure'` captures on each failed attempt, so three attempts leave three sets of images in three per-attempt folders. `'on-first-failure'` captures on the first failing attempt only, so retries add nothing. On a flaky suite that is a large reduction in near-identical files for no loss of diagnostic value.
  • The automatic screenshot shows the order tracker with no error toast visible, although the test failed on that toast. Why?
    The runner captures after the test body has ended, which is often seconds after the failing assertion, and the toast had auto-dismissed by then. Take your own `page.screenshot()` at the point of interest, or read a recorded trace, which keeps a snapshot per action rather than one picture of the aftermath.

saying these in an interview costs you the question

  • Thinks the runner captures at the instant the assertion fails
  • Believes only-on-failure also compares the image against a baseline
  • Assumes the automatic screenshot is full page by default
  • Expects images from previous runs to survive in test-results
  • Thinks a test must call page.screenshot for the option to work
  • Says the mode only captures the first page and ignores popups
open as a page

Why does Playwright's video: 'retain-on-failure' still cost time on tests that pass?

level: middleimportance: must knowfreq 58%

basics

~20 s

Because the browser records the whole test regardless. Recording starts when the context opens, long before a verdict exists, so every test pays capture, encoding and disk writes. Retain-on-failure only deletes the file afterwards when the test passed.

open as a page

In Playwright, when is locator.screenshot() a better capture than page.screenshot() with clip or fullPage?

level: middleimportance: should knowfreq 44%

basics

~20 s

Whenever the subject is one element. Playwright's locator.screenshot scrolls it into view, waits for it to be stable and measures its box at capture time, while a clip rectangle is a fixed region you computed yourself that goes stale as soon as the layout moves.

open as a page

In Playwright's page.screenshot, what does the mask option do to the captured image?

level: middleimportance: should knowfreq 31%

basics

~20 s

It takes locators and paints a solid box over each matching element's bounding box while the image is being taken, pink by default and any CSS color via maskColor. Those pixels never reach the file.

open as a page

A Playwright test writes a debug screenshot to shots/map.png, yet the run's report shows no image; why?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Writing a file is not the same as reporting one. Playwright shows attachments, so the capture must be attached with testInfo.attach, and its path should come from testInfo.outputPath so it is unique per test and per attempt.

open as a page