What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Playwright’s Python locator API to capture one element from the current page: page.locator(".header").screenshot(path="screenshot.png"). The locator scrolls the element into view, waits for it to be actionable, and saves only the element’s rendered bounds—not the browser window or the entire page.

This guide shows a complete synchronous and asynchronous setup, reliable locator choices, output options, visibility limitations, troubleshooting, and an API alternative when you do not want to run a browser locally.

What “active page element” means

Here, an active page element is a DOM element in the page currently loaded by a browser controlled through Python. It is not a screenshot of operating-system chrome, browser tabs, or the whole desktop. Playwright’s page API can capture a viewport or full page, while a locator’s screenshot() method clips the image to one matched element.

The basic pattern is:

page.locator(".header").screenshot(path="screenshot.png")

Playwright documents this element-specific pattern in its Python screenshots guide. The same method can write PNG, JPEG, or WebP output, depending on the options you pass.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install Playwright and a browser

  1. Install the Python package:
    python -m pip install playwright
  2. Install the browser binaries Playwright needs:
    python -m playwright install
  3. Save one of the scripts below and run it with Python 3.

In continuous-integration environments, run the install command during the image or job setup so the required browser is available before the script starts.

Complete synchronous example

This script opens a page, locates a heading, captures it, and closes the browser even if an error occurs.

from pathlib import Path
from playwright.sync_api import sync_playwright

URL = "https://example.com"
OUTPUT = Path("heading.png")

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    try:
        page = browser.new_page(viewport={"width": 1280, "height": 800})
        page.goto(URL, wait_until="networkidle")
        heading = page.get_by_role("heading", name="Example Domain")
        heading.screenshot(path=str(OUTPUT), animations="disabled")
        print(f"Saved {OUTPUT}")
    finally:
        browser.close()

page.goto() loads the target URL, and get_by_role() selects the heading by its accessible role and name. The locator screenshot waits for actionability and scrolls the element into view before capturing it. Disabling animations can make repeated captures more consistent.

Asynchronous Python version

Use Playwright’s async API when your application already runs an event loop or captures many pages concurrently.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        try:
            page = await browser.new_page(viewport={"width": 1280, "height": 800})
            await page.goto("https://example.com", wait_until="networkidle")
            heading = page.get_by_role("heading", name="Example Domain")
            await heading.screenshot(path="heading.png", animations="disabled")
        finally:
            await browser.close()

asyncio.run(main())

The asynchronous locator call is the same operation with await: await page.locator(".header").screenshot(path="screenshot.png").

Choose a locator that will survive page changes

Locator quality determines whether the script finds the intended element after a redesign. Playwright recommends locator-based automation because locators include auto-waiting and retry behavior. Its locator guide covers these strategies:

  • Role and accessible name: page.get_by_role("button", name="Save") or page.get_by_role("link", name="Home").
  • Visible text: page.get_by_text("Account settings").
  • Label: page.get_by_label("Email") for form controls.
  • Placeholder: page.get_by_placeholder("Search").
  • Alternative text or title: page.get_by_alt_text("Company logo") and page.get_by_title("Help").
  • Test ID: page.get_by_test_id("receipt") when the application exposes a stable test attribute.
  • CSS or XPath: page.locator("article.card") or page.locator("xpath=//main//h1") when semantic locators are unavailable.

Prefer a semantic or test-specific locator over generated class names. If a selector matches several nodes, narrow it with .first, .nth(index), or a filtering condition, but verify that the chosen match is the one you intend.

Capture one element in common situations

CSS selector

page.locator(".header").screenshot(path="header.png")

Nested component

card = page.locator("article").filter(has_text="Quarterly report")
card.screenshot(path="report-card.webp", type="webp")

Element after an interaction

page.get_by_role("button", name="Show details").click()
page.locator("#details-panel").screenshot(path="details.png")

Interactions should happen before the screenshot when the target is hidden behind a menu, tab, or disclosure control. A locator screenshot captures the element’s current rendered state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Understand exactly what gets captured

  • Element bounds: the image is clipped to the matched element’s size and position.
  • Current scroll position: a scrollable container shows only the content presently visible inside it; its off-screen children are not automatically stitched into one image.
  • Overlays remain real: cookie dialogs, modals, sticky headers, and chat widgets can cover pixels. The screenshot records what the browser displays, including that obstruction.
  • Detached nodes fail: if the page removes and recreates the element while Playwright is capturing, the operation can error. Re-locate the element after the page settles.
  • Automatic visibility handling: Playwright performs actionability checks and scrolls the element into view before the capture.

If you need the current viewport instead, use page.screenshot(path="viewport.png"). For the entire scrollable page, use page.screenshot(path="full.png", full_page=True). These page-level APIs are distinct from a locator screenshot; see the Page API reference.

Output format, animation, and repeatability

PNG is the Locator API default. You can request JPEG or WebP with the type option and choose a path with the matching extension:

target.screenshot(path="target.jpg", type="jpeg")
target.screenshot(path="target.webp", type="webp")

Use animations="disabled" to stop CSS animations, transitions, and Web Animations during capture. This is useful for documentation, visual regression checks, and generated previews. It changes the rendered state, so leave animations enabled when the animation itself is what you need to document.

Wait for dynamic content before capturing

Navigation completion does not guarantee that a component has finished rendering. Wait for a meaningful selector or state rather than adding an arbitrary long delay:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
page.goto("https://example.com/dashboard", wait_until="domcontentloaded")
report = page.locator("[data-testid='report']")
report.wait_for(state="visible")
report.screenshot(path="report.png", animations="disabled")

For data loaded after navigation, wait for the target’s text, a loading indicator to disappear, or a network response that your application controls. A locator’s built-in retries help with short timing differences, but they cannot make a permanently missing selector appear.

Common failures and fixes

“Executable doesn’t exist” or browser launch failure

Install the browser binaries with python -m playwright install. In a restricted CI image, ensure the browser dependencies and executable are included in that image.

Timeout while locating the element

Check the URL, selector, frame, and element state. Print or inspect the page after navigation, then use a more reliable role, label, test ID, or CSS selector. If the element is inside an iframe, first obtain the frame locator:

frame = page.frame_locator("iframe[title='Payment']")
frame.get_by_role("button", name="Pay").screenshot(path="pay-button.png")

Strict-mode violation

The locator matched more than one element. Narrow it by accessible name, a parent locator, .filter(), or a deliberate .nth() selection. Avoid silently choosing the first match when the page can contain duplicates.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Element is covered by a popup

Dismiss the popup or wait for it to close before capturing. A screenshot does not remove overlays; it records the visible pixels.

Only part of a long panel appears

The locator method captures the element’s rendered box and a scrollable region’s current contents. Scroll the container deliberately and capture separate states, or use a page-level full-page screenshot when the requirement is the whole document rather than one component.

Element detached from the DOM

Modern frameworks may replace nodes during rendering. Wait for the page to settle, then create a fresh locator and call screenshot() again instead of retaining a stale element handle.

Blank or inconsistent images

Confirm that navigation reached the intended page, wait for the target to become visible, disable animations when appropriate, and use a deterministic viewport. Authentication, geolocation, timezone, and data availability can also change what is rendered; configure the browser context to match the environment you need to document.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server when you want a URL captured without managing Playwright browsers. A single GET request returns PNG, JPEG, WebP, or a PDF. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status.

For an API workflow, see the ScreenshotNeo documentation. cURL:

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}`);

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. It includes 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Performance, reliability, and cost choices

  • Reuse a browser: launch Chromium once and create contexts or pages for multiple captures instead of paying startup cost for every image.
  • Control concurrency: asynchronous tasks can improve throughput, but cap parallel pages to avoid exhausting CPU, memory, or the target site’s capacity.
  • Stabilize inputs: set a fixed viewport, wait for a known ready state, and disable animations for repeatable images.
  • Choose scope carefully: an element screenshot is usually the smallest output and easiest to compare; a full-page image includes more content and may take longer to render.
  • Keep selectors maintainable: test IDs and accessible names reduce repairs when presentation-only classes change.

Playwright itself does not charge per screenshot; your costs are the machine, browser runtime, storage, and any hosted page or API service you add. ScreenshotNeo’s billing applies only to clean captures according to its returned verdict headers and current plan.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When to use a locator screenshot instead of a page screenshot

Goal Method Result
One button, card, heading, or component locator.screenshot() Clipped to the matched element
What a user sees in the current viewport page.screenshot() Viewport image
Entire document, including below the fold page.screenshot(full_page=True) Full scrollable page

Make this choice before writing selectors: selecting an element cannot produce content that is outside its current scrollable view or hidden by an overlay.

Frequently Asked Questions

Can I save the screenshot directly to memory instead of a file?

Yes. Omit the path option and use the bytes returned by the locator’s screenshot() method, then write or upload those bytes with your application.

Does a locator screenshot include the element’s CSS shadow DOM?

The capture records the pixels rendered inside the element’s bounds. Locating content inside a component still depends on how that component exposes its shadow DOM and selectors.

Should I use Selenium for this task?

Playwright’s current Python documentation provides the locator screenshot workflow described here. The available Selenium material is older and does not support a current, version-specific comparison.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.