Use Playwright’s page.screenshot() method. Launch a browser, open a page, wait for the state you need, and save the result with a filename such as screenshot.png. Set full_page=True for the entire scrollable document, or call locator.screenshot() when you need one element.
This guide shows synchronous and asynchronous Python, full-page and element captures, PNG/JPEG/WebP output, in-memory images, reproducibility controls, troubleshooting, and an API alternative when running a browser is unnecessary.
Install Playwright and a browser
Create an isolated environment if this is a project dependency, then install the Python package and browser binaries:
python -m pip install playwright
python -m playwright install chromium
The examples below use Chromium. You can launch another installed browser by replacing p.chromium with the corresponding Playwright browser type.
#1 Best Overall
Take a basic screenshot (synchronous Python)
The smallest complete synchronous script starts Playwright, launches a browser, creates a page, navigates to a URL, captures the page, and closes the browser:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto('https://example.com')
page.screenshot(path='screenshot.png')
browser.close()
Run it with python capture.py. The file extension selects the format: .png produces PNG. If you omit path, Playwright returns image bytes instead of writing a file.
Use the asynchronous API
Async Playwright is useful when your application already uses asyncio or when you capture several pages concurrently. Await browser, page, navigation, and screenshot operations:
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto('https://example.com')
await page.screenshot(path='screenshot.png')
await browser.close()
asyncio.run(main())
Keep the browser inside the async with block so Playwright shuts down cleanly even when your script grows to include more pages.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Capture a full-page screenshot
A normal screenshot covers the current viewport. Pass full_page=True to capture the complete scrollable document:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': 1440, 'height': 900})
page.goto('https://example.com')
page.screenshot(path='full-page.png', full_page=True)
browser.close()
The same option works asynchronously:
await page.screenshot(path='full-page.png', full_page=True)
Full-page capture includes content below the fold, but it does not automatically guarantee that every lazy-loaded asset has finished loading. Wait for a reliable page condition (for example, a visible selector) before capturing, and use a deliberate delay when the site has no stable condition.
Screenshot one element
Use a locator when the output should contain only a component, card, header, or other element:
page.locator('.header').screenshot(path='header.png')
page.get_by_role('link', name='Documentation').screenshot(path='documentation-link.png')
Locator screenshots perform actionability checks and scroll the element into view. If another element covers part of it, the covered pixels are not visible. For a scrollable container, only the content currently scrolled into view is captured; scroll that container first if you need a different portion.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Choose PNG, JPEG, or WebP
Playwright supports PNG, JPEG, and WebP. With a path, the extension determines the type; PNG is the default when no explicit type is supplied. You can also set type directly:
page.screenshot(path='page.jpg', type='jpeg', quality=85)
page.screenshot(path='page.webp', type='webp', quality=80)
page.screenshot(path='page.png', type='png')
| Format | Best use | Relevant option |
|---|---|---|
| PNG | Lossless UI, text, and visual-test artifacts | No quality setting |
| JPEG | Smaller photographic images where some loss is acceptable | quality from 0 to 100; default 80 |
| WebP | Modern compact images, with adjustable loss | Quality 100 is lossless; lower values are lossy |
Choose the format based on how the file will be consumed. A lower JPEG or WebP quality can reduce storage and transfer size, while PNG avoids compression artifacts around text and sharp edges.
Control viewport, device scale, and clipping
Set a viewport when responsive layout matters:
page = browser.new_page(viewport={'width': 1280, 'height': 800})
Use clip for a rectangular region in page coordinates:
page.screenshot(
path='region.png',
clip={'x': 0, 'y': 0, 'width': 600, 'height': 400}
)
By default, the output scale follows the device scale and can therefore be larger on a high-DPI display. Set scale='css' for one output pixel per CSS pixel:
Recommended Free Tools
Rank #3
page.screenshot(path='css-sized.png', scale='css')
Make captures repeatable
Disable animation
Animations and transitions can make two captures differ. Set animations='disabled'; finite animations are fast-forwarded and infinite animations are canceled for the screenshot:
page.screenshot(path='stable.png', animations='disabled')
Mask dynamic or sensitive regions
Mask locators to hide timestamps, avatars, ads, or private data. The default mask color is pink (#FF00FF); choose another with mask_color:
page.screenshot(
path='masked.png',
mask=[page.locator('.user-email'), page.locator('.live-counter')],
mask_color='#444444'
)
Inject screenshot-only CSS
The style option injects a stylesheet only for the capture. It can pierce Shadow DOM and applies inside frames, making it useful for hiding a blinking cursor or forcing a consistent visual state:
page.screenshot(
path='styled.png',
style='''
.cursor, .live-status { visibility: hidden !important; }
'''
)
Capture bytes in memory
Omit path to receive bytes. This avoids a temporary file when uploading to object storage, returning an HTTP response, or passing the image to another processor:
image_bytes = page.screenshot(type='png')
with open('screenshot.png', 'wb') as f:
f.write(image_bytes)
The asynchronous form is image_bytes = await page.screenshot(type='png').
Wait for the page state you actually need
page.goto() confirms navigation, not that every application-rendered component is ready. Prefer a meaningful condition:
page.goto('https://example.com/dashboard')
page.get_by_role('heading', name='Dashboard').wait_for()
page.screenshot(path='dashboard.png')
For a page with delayed rendering, wait for a selector, use a controlled timeout, or wait for network activity to settle according to the behavior of that application. Avoid arbitrary long sleeps when a specific locator can express readiness.
Common failures and fixes
“Executable doesn’t exist” or browser launch failure
Install the browser binaries for the Playwright version in your environment:
python -m playwright install chromium
In a restricted CI image, also verify that the process has permission to launch the browser and that required system dependencies are available.
The screenshot is blank or only partly rendered
- Wait for a visible, application-specific locator before calling
screenshot(). - Check that the URL is reachable from the machine running the script.
- For lazy content, scroll or wait for the relevant content to appear before a full-page capture.
- Inspect the page for an authentication redirect, consent dialog, or bot challenge.
An element screenshot fails because the element is not actionable
Use a locator that uniquely identifies the element, wait for it, and make sure it is not hidden or covered. A locator screenshot scrolls the target into view, but it cannot reveal pixels obscured by another layer.
The image is unexpectedly huge
Reduce the viewport, capture a locator instead of the whole page, or set scale='css'. Full-page and high device-scale captures can legitimately produce large files.
Visual tests change between runs
Disable animations, mask dynamic regions, set a fixed viewport and color scheme, and inject a stable stylesheet with style. Also control test data and wait for a deterministic readiness locator.
Free tools Windows power users keep installed
One-click scans. No signup required.
JPEG or WebP output is rejected by a downstream system
Confirm the extension and explicit type agree with the consumer. Use PNG when a pipeline accepts only lossless PNG or when exact text rendering matters.
Performance, reliability, and cost considerations
Playwright runs a real browser, so each capture includes browser startup, navigation, page rendering, and image encoding. Reuse one browser process for multiple pages, create contexts or pages per job, and close them when work is complete. Capture only the scope you need: an element or clipped region is usually less work than a very long full-page image.
For reliable automation, use explicit readiness conditions, fixed viewport settings, disabled animations, and masks. There is no general performance benchmark established here; actual time and memory depend on the site, browser, network, page length, and image format.
In a self-hosted script, your main costs are compute, browser memory, and network transfer. A service may be preferable when you do not want to maintain browser binaries, concurrency controls, retries, or cleanup.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or a PDF, so you can capture a URL without installing Playwright or managing a browser process:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo documentation for request options. It removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server includes take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Playwright screenshot checklist
- Install Playwright and the browser binary.
- Choose sync or async API to match your application.
- Set a deterministic viewport and wait for a meaningful ready state.
- Use
full_page=Truefor the complete scrollable document. - Use
locator.screenshot()for a component or element. - Select PNG, JPEG, or WebP and set quality where applicable.
- Disable animations, mask changing data, clip unnecessary regions, and choose
scale='css'when pixel dimensions must be predictable. - Close pages and browsers after the capture.
Frequently Asked Questions
Can Playwright save a screenshot without writing a file?
Yes. Omit the path argument; page.screenshot() returns image bytes that you can upload or process in memory.
What does full_page=True include?
It captures the page’s full scrollable document rather than only the current viewport. Wait for lazy content before calling it if below-the-fold assets matter.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsHow do I capture a component inside a page?
Create a locator and call locator.screenshot(path='component.png'). Playwright checks actionability and scrolls the element into view.
Which format should I use for visual regression tests?
PNG is the safest default for lossless text and interface pixels. JPEG and WebP can reduce size when compression artifacts are acceptable.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




