Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Playwright to open a webpage in a real browser and save an image of its rendered contents. Install the Python package and its browser binaries, navigate to the page, then call page.screenshot(). By default, that captures the current viewport; set full_page=True for the full scrollable page, or take a screenshot of a locator to capture one element.
Install Playwright and its browser
Playwright drives a browser to render the page before taking the screenshot. Install the Python library and the browser binaries it needs:
python -m pip install playwright
python -m playwright install
Using python -m runs each command through the Python interpreter associated with python. This can help keep the package installation and browser setup aligned with the Python environment you intend to use. If your system uses a different command to invoke Python, use that same interpreter for both commands.
Playwright supports Chromium, Firefox and WebKit, and its browser launches headlessly by default. The example below uses Chromium. Playwright releases depend on compatible browser binaries, so after updating the package, rerun the browser-install command if the browser is missing or no longer matches. Operating-system requirements can change; consult the current official Playwright installation and browser-management guides for your environment.
#1 Best Overall
Take a basic webpage screenshot
Save this as screenshot.py and run it with Python. It writes screenshot.png in the current working directory:
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()
Replace https://example.com with the URL you want to capture. A call to page.goto() navigates the browser, and page.screenshot() captures what is rendered in the current viewport. The with block manages the Playwright context; the explicit browser.close() releases the browser when the capture is finished.
The sample follows the documented synchronous API. It is a minimal starting point, not a guarantee that every site’s application-specific content has finished rendering. Pages that fetch data after navigation, load images as you scroll, or animate content may need an additional wait condition suited to that page.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Choose what to capture
Current viewport
The basic call captures the visible browser viewport:
page.screenshot(path="screenshot.png")
This is useful when you want the page as it appears at one screen position. The viewport dimensions affect the resulting composition; set them when creating the page if you need a particular browser window size:
Rank #2
page = browser.new_page(viewport={"width": 1440, "height": 900})
Full scrollable page
Set full_page=True to capture the full scrollable document rather than only the visible area:
page.screenshot(path="full-page.png", full_page=True)
A full-page capture can be much taller and larger than a viewport image. It does not, by itself, establish that all lazy-loaded images or application content have loaded; those behaviors depend on the site. If content appears only after scrolling, the page may need a deliberate scroll-and-wait routine before capture.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →One element
Use a locator when you only need one matching element, such as a header, chart or card:
page.locator(".header").screenshot(path="header.png")
Replace .header with a CSS selector for the element you want. If the selector does not match an element, or the element is not ready, the capture cannot produce the intended image. Check the selector against the page and wait for the relevant element when the page renders it asynchronously.
Save a file or use screenshot bytes
Passing path saves the screenshot directly to a file. If you omit it, Playwright returns the image as bytes, which you can pass to another Python library or write yourself:
image_bytes = page.screenshot()
with open("screenshot.png", "wb") as image_file:
image_file.write(image_bytes)
Bytes are useful when the next step is in-memory processing or an upload rather than a file on disk. The screenshot API documents PNG, JPEG and WebP output. The image type can be inferred from the output path extension; for in-memory output, set the screenshot type option explicitly if needed.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesjpeg_bytes = page.screenshot(type="jpeg", quality=80)
webp_bytes = page.screenshot(type="webp", quality=80)
Quality applies to lossy JPEG or WebP encoding; it is not a way to improve the detail of the rendered page. Use PNG when you want lossless output, or choose JPEG/WebP when their smaller encoded output better suits your use. The appropriate format depends on downstream needs.
Control size, clipping and timeout
The screenshot API includes options for clipping a region, image quality and scale. A clip is useful when you want a rectangular portion of the page rather than the whole viewport:
page.screenshot(
path="region.png",
clip={"x": 100, "y": 120, "width": 600, "height": 400},
)
Clip coordinates and dimensions are expressed relative to the page’s screenshot coordinate space. Make sure the region lies within the content you intend to capture.
Scale controls the relationship between CSS pixels and output image pixels. With CSS scale, one image pixel corresponds to one CSS pixel; device scale uses device pixels and can produce larger images on high-density displays. For example:
Free tools Windows power users keep installed
One-click scans. No signup required.
page.screenshot(path="css-scale.png", scale="css")
page.screenshot(path="device-scale.png", scale="device")
The documented screenshot timeout defaults to 30,000 milliseconds. You can set a different timeout for a particular capture, in milliseconds:
page.screenshot(path="screenshot.png", timeout=60000)
Increasing this limit can help when the screenshot operation itself needs more time, but it does not fix a page that has not reached the state you want. For dynamic content, identify the relevant readiness condition rather than relying on a longer screenshot timeout alone.
Wait for the page state you actually need
A navigation returning is not the same thing as every site-specific component being ready. For example, a page may insert a chart after an API response or show an image only after it becomes visible. Choose a condition that represents the content you want to capture.
If a known element indicates readiness, wait for it explicitly:
page.goto("https://example.com")
page.locator(".report-ready").wait_for()
page.screenshot(path="report.png")
Use a selector that actually represents readiness on the target site; .report-ready is an example, not a universal class. A fixed delay is another option when a site has a known, predictable pause, but it can waste time on fast loads and still be too short on slow ones. Avoid treating a single wait strategy as reliable for every website.
Best Value
For full-page screenshots involving lazy-loaded images, scrolling through the content and allowing the site to load visible material may be necessary. Whether that is required depends on how the page implements lazy loading.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Use Playwright with asyncio
If the surrounding program already uses Python’s asynchronous event loop, Playwright provides an asynchronous API as well. The browser actions are awaited, while the context manager still ensures orderly cleanup:
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())
Use the synchronous example for a simple standalone script. Use the asynchronous form when integrating the capture into an async application; do not call asyncio.run() from within an event loop that is already running. In that situation, await main() from the existing async code instead.
Recommended Free Tools
Common problems and fixes
- Browser executable missing: Install the browser binaries with
python -m playwright installusing the same Python environment as the package. - Browser and package do not match after an update: Rerun the Playwright browser-install command after updating the package. Browser binaries are tied to Playwright releases.
- The screenshot is blank or incomplete: Check that the URL is correct and the page reached the state you need. If content appears asynchronously, wait for a relevant selector or another site-appropriate readiness condition before capturing.
- Full-page image is missing content loaded on scroll: Full-page capture covers the scrollable document, but does not guarantee that all lazy-loaded content was triggered. Scroll through the relevant area and allow the site to load it before taking the screenshot.
- Element capture fails or targets the wrong item: Verify the locator matches the intended element and wait for it to appear before calling its screenshot method.
- Output is in the wrong folder: A relative path such as
screenshot.pngis resolved from the script’s current working directory. Use an absolute path or inspect the directory from which you launched Python. - Screenshot operation times out: The screenshot call has a documented default timeout of 30,000 milliseconds. Raise the timeout only if the capture needs more time, and separately diagnose any page-readiness issue.
- Image is larger than expected: Full-page captures can be very tall, and device scale can increase pixel dimensions on high-density displays. Choose viewport capture or CSS scale when those dimensions better fit the task.
Or skip the browser setup
If you would rather request a screenshot than manage a browser locally, ScreenshotNeo is a website screenshot API. Its Python example makes one GET request and saves the response body as an image:
ScreenshotNeo API documentation
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)
Replace YOUR_API_KEY with your API key and change the target URL as needed. ScreenshotNeo removes cookie and consent banners, newsletter popups and chat widgets before capture; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides screenshot tools for AI agents, and the service offers 1,000 screenshots per month free without a card; paid plans start at $5 for 3,000 screenshots.
Frequently Asked Questions
Can I capture a webpage as a WebP image with Playwright Python?
Yes. Use page.screenshot(path="shot.webp") or set type="webp".
Can Playwright capture a page in Firefox or WebKit instead of Chromium?
Yes. Playwright supports Chromium, Firefox and WebKit; install the browser binaries needed for the browser you choose.
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.

