Keyword: playwright screenshot · Updated October 15, 2026
Playwright Screenshot: Every Option Explained (Full Page, Element, Scrollable Div) + Copy-Paste Code
The one-line version of a Playwright screenshot fits in a tweet. The trouble starts afterwards: the full-page capture stops at the fold of a chat panel, the image is twice the size you expected, a carousel moves between runs, or a cookie banner covers the button you wanted to show. This page lists every option of page.screenshot() and locator.screenshot() with TypeScript and Python examples, and gives a working fix for scrollable containers.
The basic screenshot
TypeScript / JavaScript:
Python (sync API):
Without options you get the visible viewport as a PNG. The format comes from the file extension, so example.jpeg or example.webp switch formats without any other change.
Every page.screenshot() option
Python uses snake_case for the same options (full_page, omit_background, mask_color). Defaults are from the current Playwright API reference.
| Option (TS / Python) | Default | Use it for |
|---|---|---|
path | none | File to write. Without it, nothing is saved and you only get the buffer. |
type | png | png, jpeg or webp. |
quality | jpeg 80, webp 100 | 0 to 100. Ignored for PNG. WebP at 100 is lossless. |
fullPage / full_page | false | Capture the whole scrollable document. |
clip | none | { x, y, width, height } region of the page. |
scale | "device" | "css" gives one pixel per CSS pixel and smaller files on high-DPI contexts. |
animations | "allow" | "disabled" fast-forwards finite animations and resets infinite ones. |
caret | "hide" | Hides the blinking text cursor. Set "initial" to keep it. |
mask | none | Array of locators to cover with a solid box (timestamps, avatars, ads). |
maskColor / mask_color | #FF00FF | Color of the mask boxes. Added in v1.35. |
style | none | CSS applied only while the screenshot is taken. Pierces Shadow DOM and iframes. Added in v1.41. |
omitBackground / omit_background | false | Transparent background instead of white. Not for JPEG. |
timeout | see docs | Max time in ms. Configurable globally with page.setDefaultTimeout() or actionTimeout. |
signal | none | An AbortSignal to cancel the capture. Added in v1.62. |
locator.screenshot() accepts the same set except fullPage and clip, because the element defines the area.
Full page screenshot
fullPage captures the document as if the window were tall enough to fit it. It does not scroll the page first, so images with loading="lazy" below the fold may still be empty. Scroll before capturing:
networkidle for tests and recommend web-first assertions instead. For a one-off capture script it is still a reasonable "network has calmed down" signal. In tests, wait for a specific element with await expect(locator).toBeVisible().Screenshot of one element
The locator waits for the element to be visible and scrolls it into view. If the locator matches several elements, Playwright throws a strict mode error instead of guessing. Narrow it with .first() or a better selector.
Screenshot of a scrollable element (the part most guides skip)
Searches for "playwright screenshot scrollable element" exist because fullPage only expands the document. A chat log, a data grid or a sidebar with its own overflow: auto stays at its fixed height, and you get the visible slice. There are three ways around it.
Option A: remove the height limit before capturing
Add a stylesheet that lets the container grow to its content, then capture it. This works for most layouts.
Virtualized lists (react-window, AG Grid with row virtualization) only render visible rows, so growing the container shows empty space. For those, use option C or turn virtualization off in a test build.
Option B: full page with an app shell
Many dashboards set html, body { height: 100% } and scroll inside main. Then fullPage: true returns exactly one viewport. Apply the same CSS idea to the shell and take a full-page shot:
Option C: capture in steps
Scroll the container one height at a time and save each slice. You can stitch them with an image library afterwards or keep them as a numbered set for review.
Make screenshots stable between runs
If you compare screenshots or attach them to reports, dynamic content causes noise. Three options handle most of it:
Use mask when the element should stay visible as a placeholder (reviewers see that something was there). Use style with display: none when it should disappear completely. The style option is removed after the capture, so the page is unchanged for the rest of the test.
Fonts are the other common source of differences. Wait for them explicitly before capturing pages with web fonts: await page.evaluate(() => document.fonts.ready).
Size, retina and format
| Goal | Setting |
|---|---|
| Sharp retina image | browser.newPage({ deviceScaleFactor: 2 }) and keep scale: "device" |
| Same pixel size on every machine | scale: "css" |
| Mobile screenshot | browser.newContext({ ...devices["iPhone 15"] }) |
| Small files for thumbnails | type: "webp", quality: 70 or type: "jpeg", quality: 75 |
| Transparent PNG of a logo or widget | omitBackground: true and a transparent page background |
| Dark mode | browser.newContext({ colorScheme: "dark" }) |
Get a buffer or base64 instead of a file
Use the buffer when you upload to S3, send the image to a vision model or attach it to a Slack message. Skipping the disk write also avoids clean-up in CI.
Screenshots in Playwright Test
For tests, let the runner handle screenshots instead of calling page.screenshot() in every test:
The modes are off (default), on, only-on-failure and on-first-failure. Screenshots are attached to the test results and show up in the HTML report.
For explicit evidence inside a test, attach the image to the report:
Pixel comparisons with toHaveScreenshot() are a separate topic with their own thresholds and baselines. Our visual regression testing guide covers that workflow.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Full page is only one screen tall | The app scrolls inside a container, not the document | Option B above |
| Blank areas where images should be | Lazy loading | Scroll the page before capturing |
| Text in a fallback font | Web fonts not loaded yet | await page.evaluate(() => document.fonts.ready) |
| Image is 2x larger than viewport | scale: "device" with deviceScaleFactor: 2 | scale: "css" |
| Strict mode violation on element screenshot | Locator matches more than one element | Use a narrower locator or .first() |
| Cookie banner covers the page | Consent manager overlay | style option with display: none, or click "Reject" first |
| Screenshot times out | Element never becomes visible | Check the selector, then raise timeout |
When you need screenshots outside tests
Playwright is the right tool inside a test suite. For product features such as link previews, scheduled page archives or capturing thousands of customer URLs, you end up running a browser fleet: memory limits, crashed Chromium processes, font packages in Docker and queueing. A screenshot API moves that work off your servers.
The options map almost one to one. Here is the scrollable-page case with SnapshotFlow:
For a full mapping of Playwright options to API parameters and a cost comparison, see Playwright alternative for screenshots.
FAQ
How do I take a full page screenshot in Playwright Python?
page.screenshot(path="page.png", full_page=True). Note the snake_case name; fullPage raises an error in Python.
Can Playwright take a screenshot in WebP?
Yes. type: "webp" is supported in current versions. At the default quality of 100 it is lossless; lower values switch to lossy compression.
Does fullPage work in Firefox and WebKit?
Yes, fullPage works in all three Playwright browsers. Rendering details such as font smoothing differ between engines, so do not compare screenshots across browsers pixel by pixel.
How do I take a screenshot only when a test fails?
Set use: { screenshot: "only-on-failure" } in playwright.config.ts. For Python with pytest-playwright, pass --screenshot only-on-failure.
Sources and further reading
- page.screenshot() API reference
- locator.screenshot() API reference
- testOptions.screenshot for automatic screenshots in Playwright Test.
- Full page screenshot API and element screenshot API on this blog.
Try it: 300 free screenshots, no card
Keep Playwright for your tests. For screenshots your product or reports depend on, send one HTTP request and get the image back, with full page, retina, WebP and cookie-banner blocking built in.