In Playwright, when is locator.screenshot() a better capture than page.screenshot() with clip or fullPage?
answer
- One frames a page, one frames an element
- Coordinates versus a live box
- Scroll and stability come free on one side
- fullPage and clip are page-only
- Overlays still land in the frame
basics
~20 sWhenever 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.
solid answer
~50 s`page.screenshot()` photographs the page: the viewport by default, the whole scrollable document with `fullPage: true`, or a fixed rectangle with `clip: { x, y, width, height }`. `locator.screenshot()` photographs one element: it scrolls the element into view, waits for it to be visible and stable, then clips to the box it measures at that moment. So for a single widget -- the driver map card on an order tracker -- the locator form is more robust, because it re-measures instead of trusting coordinates you captured earlier. `fullPage` and `clip` exist only on the page API; `mask`, `maskColor`, `animations`, `caret`, `omitBackground`, `scale`, `type`, `quality`, `path` and `timeout` are common to both. Either returns a Buffer when `path` is omitted. Element capture still shows any overlay covering the element, and a scrollable element only shows its current scroll position.
code
typescript · 7 linesimport { test } from '@playwright/test';
test('driver map renders', async ({ page }) => {
await page.goto('/orders/8842');
const card = page.getByTestId('driver-map-card');
await card.screenshot({ path: test.info().outputPath('driver-map.png') });
});go deeper
Recall that page.screenshot frames the page, with fullPage and clip as its options, while locator.screenshot frames a single element and needs no coordinates from you.
Explain why element capture is more robust: it scrolls into view, waits for stability and measures the box at capture time, whereas a clip rectangle is stale the moment the layout moves.
Show the failure mode in practice, that a stale crop silently captures the wrong pixels, and choose per situation between full-page evidence and small element captures for report size and review speed.
Set the convention for what a suite captures and how large its evidence is allowed to be, so reports stay openable and reviewers get the frame that answers the question.
## Two different subjects Both APIs write a PNG or JPEG; they differ in what the frame is *about*. - `page.screenshot()` -- the subject is the page. By default it captures the viewport; `fullPage: true` captures the whole scrollable document; `clip: { x, y, width, height }` captures a fixed rectangle in CSS pixels relative to the page. - `locator.screenshot()` -- the subject is one element. Playwright scrolls it into view, waits for actionability (attached, visible, and not animating), measures its bounding box **at that moment** and clips to it. The second is not a convenience wrapper over the first. The measurement happens at capture time, which is the entire reason to prefer it. ## What only the page API can do | Capability | `page.screenshot()` | `locator.screenshot()` | |---|---|---| | Whole scrollable document (`fullPage`) | yes | no | | Arbitrary rectangle (`clip`) | yes | no | | Auto scroll-into-view of the subject | no | yes | | Waits for the subject to stop animating | no | yes | | `mask` / `maskColor` | yes | yes | | `omitBackground`, `animations`, `caret`, `scale`, `style` | yes | yes | | Returns a Buffer when `path` is omitted | yes | yes | ## Why a clip rectangle goes stale A `clip` is numbers, and numbers do not follow the DOM. To crop the driver-map card on an order tracker with `clip` you must first read its box with `locator.boundingBox()`, then pass those coordinates to `page.screenshot()`. Between those two calls the page can: 1. finish loading a promotion banner above the card, pushing it down; 2. settle a layout shift as a web font swaps in; 3. re-render the live status strip and change the card's height. Any of those makes the rectangle photograph the wrong pixels -- silently, because a crop cannot fail. `locator.screenshot()` collapses the two steps into one operation that measures and captures together, and it fails loudly with a timeout if the element never becomes visible or never settles. ## What element capture still cannot do - **Overlays are not removed.** If a cookie banner or a modal covers the card, the capture shows the banner. The frame is the element's *region*, not the element in isolation. - **Scrollable elements show only what is scrolled into view.** A long order-history list clipped to its container is captured at its current scroll position, not in full. - **Off-screen size still applies.** An element taller than the viewport is captured whole, so the page scrolls during capture -- fine for static content, awkward for sticky headers. - **It is still evidence, not a reference.** Comparing an element image against an approved baseline is a different mechanism with its own approval flow. ## Choosing in practice 1. One widget, and you know its locator: `locator.screenshot()`. 2. The whole page as failure evidence: `page.screenshot({ fullPage: true })`. 3. A region defined by geometry rather than by an element -- a fixed area of a canvas-rendered map, for example: `page.screenshot({ clip })`, taken as close in time to the measurement as you can. ## A worked shape ```ts const card = page.getByTestId('driver-map-card'); await card.screenshot({ path: test.info().outputPath('driver-map.png'), mask: [page.getByTestId('customer-address')], }); ``` That capture scrolls the card into view, waits for it to settle, masks one region, and writes into the test's own output folder. The `page.screenshot({ clip })` equivalent needs a `boundingBox()` call, a null check, and an assumption that nothing moved in between. ## Cost and legibility Full-page captures on a long tracker page can run to several megabytes each and are slow to open in a report. Element captures are small and are what a reviewer actually wants when the failure is localised. A useful habit: full page for the automatic failure evidence, element captures for the specific thing a test was asserting about.
- A modal overlays the driver-map card. What does locator.screenshot() produce, and how would you get a clean image?It produces the card's region with the modal drawn over it, because the capture is a crop of the rendered page, not an isolated render of the element. Dismiss or close the overlay first, or capture in a state where it is not shown; there is no option that renders an element free of what covers it.
- When would you still reach for page.screenshot with clip?When the region is defined by geometry rather than by an element -- a fixed quadrant of a canvas-drawn map, or an area spanning several unrelated nodes. Measure and capture as close together as possible, since the rectangle carries no relationship to the DOM and will not notice a layout shift.
saying these in an interview costs you the question
- Thinks locator.screenshot accepts fullPage or clip
- Believes element capture hides overlapping elements
- Computes a clip rectangle early and reuses it later
- Assumes a scrollable container is captured in full
- Says only the page API can mask regions