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 minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use page.screenshot(full_page=True). In Playwright’s Python API, that option captures the page’s full scrollable area instead of only the visible viewport. Add a path to save an image, or omit it to receive image bytes for further processing.
This guide covers synchronous and asynchronous scripts, output formats, waiting for dynamic content, test-runner screenshots, common failures, and a browser-free API alternative.
Install Playwright and its browsers
Install the Python package, then download the browser binaries you intend to run. Chromium is sufficient for the examples below.
pip install playwright
playwright install chromium
Playwright’s library workflow is documented in the Python library guide. You need Python, a Playwright browser, a URL that can be loaded, and permission to write the output file.
#1 Best Overall
Capture a full page in a synchronous script
The smallest complete program is:
from playwright.sync_api import sync_playwright
with sync_playwright() as playwright:
browser = playwright.chromium.launch()
page = browser.new_page()
page.goto("https://example.com")
page.screenshot(path="screenshot.png", full_page=True)
browser.close()
full_page=True is the important setting. Its documented default is False, which captures only the current viewport. The full-page mode renders the page’s scrollable area as though it fit on a very tall screen; it is not the same as an ordinary viewport screenshot. See the official screenshot guide.
Wait for navigation and page state
page.goto() waits for the navigation to reach its normal load state, but modern pages can continue fetching data, fonts, or images afterward. Wait for a page-specific signal before capturing:
page.goto("https://example.com", wait_until="domcontentloaded")
page.locator("main").wait_for(state="visible")
page.screenshot(path="screenshot.png", full_page=True)
Use a locator that genuinely indicates readiness, such as a results table or article heading. A fixed delay can help with an animation or a known short transition, but a semantic wait is usually more reliable.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteUse the asynchronous Python API
Choose async when your application already uses asyncio, an async web service, or concurrent browser work. The call is the same apart from await:
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as playwright:
browser = await playwright.chromium.launch()
page = await browser.new_page()
await page.goto("https://example.com")
await page.screenshot(path="screenshot.png", full_page=True)
await browser.close()
asyncio.run(main())
The sync and async APIs expose the same full-page option. Do not call the synchronous API from inside an active event loop; use the async version there. The lifecycle pattern—launch, create a page, navigate, capture, close—is described in the library documentation.
Rank #2
Save a file or process screenshot bytes
Write directly to disk
Set path for a simple artifact:
page.screenshot(path="artifacts/home.webp", full_page=True, type="webp", quality=85)
The screenshot API supports PNG, JPEG, and WebP. JPEG and WebP accept a quality value. Ensure the parent directory exists before writing, or create it with Python’s pathlib.
Keep the image in memory
Without path, page.screenshot() returns image bytes:
image_bytes = page.screenshot(full_page=True, type="png")
with open("screenshot.png", "wb") as output:
output.write(image_bytes)
Bytes are useful when uploading to object storage, attaching a test report, hashing an image, or passing it to an image-processing library without a temporary file.
Options that matter for full-page captures
| Need | Option or method | Effect |
|---|---|---|
| Entire scrollable page | full_page=True |
Captures the full page rather than the viewport. |
| One element | locator.screenshot() |
Captures the element’s bounding box instead of the whole document. |
| Specific region | clip={"x": ..., "y": ..., "width": ..., "height": ...} |
Restricts the capture to a rectangle. |
| Stable visual output | animations="disabled" |
Disables supported CSS animations and transitions during capture. |
| One output pixel per CSS pixel | scale="css" |
Avoids larger high-DPI output caused by the device scale factor. |
| More time for slow pages | timeout=... |
Sets the screenshot operation timeout in milliseconds. |
| Format | type="png", "jpeg", or "webp" |
Selects the encoded image format; quality applies to JPEG/WebP. |
These parameters and defaults are defined in the Page API reference. Keep the viewport explicit when reproducibility matters:
page = browser.new_page(viewport={"width": 1440, "height": 900}, device_scale_factor=1)
page.goto("https://example.com")
page.screenshot(
path="page.png",
full_page=True,
scale="css",
animations="disabled",
timeout=60_000,
)
Dynamic, lazy-loaded, and infinite-scroll pages
Full-page mode captures the page’s scrollable layout, but the screenshot documentation does not promise that the call itself scrolls through the page to trigger every lazy-loaded image or loads an infinite-scroll feed. If content appears only after scrolling, load it explicitly before taking the screenshot.
from playwright.sync_api import sync_playwright
with sync_playwright() as playwright:
browser = playwright.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/feed")
previous_height = 0
for _ in range(20):
height = page.evaluate("document.body.scrollHeight")
if height == previous_height:
break
previous_height = height
page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
page.wait_for_timeout(500)
page.screenshot(path="feed.png", full_page=True)
browser.close()
Use a bounded loop and a real completion condition for production pages. Infinite feeds may never settle; decide how many items or what maximum height you need. For lazy images, wait for a representative image selector or verify that image elements have loaded before capture.
Full-page screenshots in pytest
If you use Playwright’s Python pytest plugin, failure screenshots are configured at test-runner level rather than by adding full_page=True to a standalone call. The plugin’s --full-page-screenshot option requires screenshot capture to be enabled with --screenshot:
pytest --screenshot only-on-failure --full-page-screenshot
These flags apply to the test runner. For a custom artifact inside a test, call page.screenshot(path=..., full_page=True) yourself. Refer to the pytest plugin reference for the supported values and configuration.
Troubleshooting
The image contains only the visible area
Pass full_page=True to page.screenshot(). Check that you did not accidentally call locator.screenshot(), which is intended for one element.
The bottom of the page is blank or content is missing
Wait for the application’s data-ready selector, images, or fonts. If the site uses lazy loading or infinite scroll, scroll and trigger that content before capturing; full-page mode alone does not guarantee deferred content is loaded.
Free tools Windows power users keep installed
One-click scans. No signup required.
The screenshot times out
Find the slow operation rather than immediately using an unlimited timeout. Confirm the URL is reachable, wait for a narrower selector, and then raise the screenshot timeout for a known-slow page, for example timeout=120_000. Also check for a page that never finishes its own network activity.
The file cannot be written
Use an absolute or valid relative path, create the parent directory, and check filesystem permissions. If you only need to transmit the image, omit path and handle the returned bytes.
Output dimensions or file size are unexpectedly large
A long document naturally creates a tall image. Use scale="css", JPEG/WebP with an appropriate quality value, or capture a specific element or clip. A very tall page may also be better represented as several sections or a PDF, depending on the consumer.
Sync code fails inside an async application
Replace sync_playwright with async_playwright, add await to browser, page, navigation, and screenshot calls, and run the coroutine with your application’s event loop.
Performance, reliability, and security notes
- Reuse a browser process when taking many screenshots, but create isolated contexts when cookies, authentication, locale, or viewport settings must not leak between jobs.
- Set an explicit viewport and scale when pixel dimensions are part of a visual regression comparison.
- Close pages, contexts, and the browser in cleanup paths so failed captures do not accumulate resources.
- Use a selector-based readiness check instead of a long arbitrary sleep whenever the page exposes a reliable state signal.
- Be careful with authenticated pages and sensitive query strings: screenshots can contain private data, and saved files inherit the permissions of their destination.
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.
See the ScreenshotNeo API documentation for all options, including full-page capture, lazy-image loading, CSS-selector element capture, device presets, retina scale, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data, and the OpenAPI specification. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
Best Value
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Every feature is included on every plan. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to get started.
Choosing the right capture method
| Situation | Best fit |
|---|---|
| Local debugging or browser-level interaction | Playwright sync or async API |
| Existing asyncio service | Async Playwright |
| Need bytes for another Python step | Omit path |
| Automatic failure artifacts in pytest | --screenshot with --full-page-screenshot |
| Many URLs, consent cleanup, or AI-agent access | ScreenshotNeo API or MCP server |
Frequently Asked Questions
Does full_page=True create a PDF?
No. It returns an image (PNG by default, or JPEG/WebP when selected). Use a PDF-capable workflow when the required artifact is a document rather than an image.
Recommended Free Tools
Can I capture a single element instead of the whole page?
Yes. Call locator.screenshot() on the element locator; use page-level full_page=True for the complete scrollable document.
Which Playwright Python versions support these APIs?
The exact available options can vary by installed Playwright release. Check the version-specific release notes and API reference when upgrading.
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.

