Free tools Windows power users keep installed
One-click scans. No signup required.
Call Playwright’s screenshot method without a path. The method returns the image as Python bytes, so you can send it to an API, encode it as Base64, inspect it with Pillow, or store it later on your own terms. Use page.screenshot() with the synchronous API and await page.screenshot() with the asynchronous API.
What “in-memory screenshot” means
A normal Playwright screenshot can write directly to a filename when you provide path. An in-memory screenshot omits that argument. Playwright renders the page and returns the encoded image bytes to your Python process instead of creating an image file.
The returned value is binary data, not a filename and not a decoded pixel array. Keep it as bytes while passing it to another component, or decode it with an image library when you need to inspect or transform the image.
Install Playwright and its browser
Install the Python package in the environment that will run your script, then install the browser binaries:
Recommended Free Tools
#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
python -m pip install playwright
python -m playwright install chromium
Use a virtual environment for repeatable deployments. The examples below use Chromium, but the same API shape applies to the other Playwright browser engines that your installation supports.
Take an in-memory screenshot with synchronous Playwright
For a conventional script that does not run inside asyncio, use sync_playwright. The result of page.screenshot() is assigned directly to screenshot_bytes.
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")
screenshot_bytes = page.screenshot()
print(type(screenshot_bytes), len(screenshot_bytes))
# Pass screenshot_bytes to an image processor, HTTP client, or queue.
browser.close()
There is no path argument, so this code does not ask Playwright to save an image. Close the browser even when you are finished with the bytes; the context manager closes the Playwright driver, but explicit browser cleanup releases the browser process promptly.
Wait for the page state you actually need
page.goto() waits for the navigation event selected by its defaults, not necessarily for every image, font, animation, or application request to finish. If the screenshot must represent a known state, wait for a selector, a specific load state, or an application condition before capturing:
page.goto("https://example.com", wait_until="domcontentloaded")
page.locator("main").wait_for(state="visible")
screenshot_bytes = page.screenshot()
A selector wait is usually more meaningful than an arbitrary sleep. Use a timeout appropriate to your site and handle a timeout as a page-readiness failure rather than silently returning an incomplete image.
Take an in-memory screenshot with asynchronous Playwright
Use the async API when your application already uses asyncio, an async web framework, or concurrent browser work. Await the screenshot call; the returned value is still Python bytes.
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")
screenshot_bytes = await page.screenshot()
print(type(screenshot_bytes), len(screenshot_bytes))
await browser.close()
asyncio.run(main())
Do not call synchronous Playwright APIs from an active event loop. Choose one API style for a given execution path. The async API is appropriate when other work must progress while browser operations are awaited.
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
Choose the capture region
Viewport capture (the default)
A page screenshot without special options captures the current viewport. Set the viewport explicitly when reproducible dimensions matter:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
page.set_viewport_size({"width": 1440, "height": 900})
screenshot_bytes = page.screenshot()
Viewport dimensions are CSS pixels. Device scale and the selected browser/device descriptor affect the resulting image dimensions.
Full-page capture
Set full_page=True to capture the page’s full scrollable height rather than only what is visible:
screenshot_bytes = page.screenshot(full_page=True)
Very tall pages create large images and may expose lazy content only after it has been loaded. If the site loads content on scroll, trigger the page’s loading behavior first and verify that the resulting page has reached the intended state.
Capture one element
Use a locator’s screenshot() method for a component such as a card, chart, or header:
Windows 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 reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchcard_bytes = page.locator(".pricing-card").screenshot()
In async code, use await page.locator(".pricing-card").screenshot(). Playwright scrolls the element into view and waits for actionability. If another element covers it, the screenshot does not magically make the covered content visible. A scrollable container captures the content currently visible in that container, not every off-screen child.
Set image format, quality, scale, and background
PNG is the default. You can request JPEG or WebP with type:
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
png_bytes = page.screenshot(type="png")
jpeg_bytes = page.screenshot(type="jpeg", quality=80)
webp_bytes = page.screenshot(type="webp", quality=85)
- PNG: lossless; the
qualityoption does not apply. - JPEG: lossy and usually smaller for photographic pages; quality is an integer from 0 through 100, with the documented default of 80.
- WebP: supported by current Playwright releases; quality 100 is lossless and lower values are lossy. Check your installed version because format support can change. The Playwright release notes record WebP screenshot support in version 1.62.
The scale option controls output density. scale="device" is the default and uses device pixels; scale="css" produces one output pixel per CSS pixel and can reduce high-DPI image size:
screenshot_bytes = page.screenshot(scale="css")
For transparency-capable captures, omit_background=True removes the default background. It does not apply to JPEG:
transparent_png = page.screenshot(omit_background=True, type="png")
Control dynamic or sensitive content
Animated elements can produce different frames on different runs. Playwright’s screenshot options include animation handling, masking, and a stylesheet option. Use these when you need a repeatable visual or must hide selected regions, and confirm the result on the page you are capturing.
Mask a locator
masked = page.screenshot(
mask=[page.locator(".account-email"), page.locator(".billing-address")],
mask_color="#000000",
)
Masking covers matched regions in the screenshot; it does not remove the underlying data from the page or from network responses. Treat the original page and browser context as sensitive even when the output is masked.
Apply a temporary stylesheet
stable = page.screenshot(
style="""
*, *::before, *::after {
animation: none !important;
transition: none !important;
}
"""
)
Use a narrowly scoped stylesheet when possible. Disabling every transition can alter layout timing, so wait for the final state after applying any visual overrides.
Use the bytes without writing a file
Base64 for JSON or HTML
import base64
encoded = base64.b64encode(screenshot_bytes).decode("ascii")
data_url = "data:image/png;base64," + encoded
Base64 increases payload size, so send raw bytes when the receiving interface accepts binary data. A data URL is convenient for embedding in a JSON response or an HTML img element.
Inspect or resize with Pillow
from io import BytesIO
from PIL import Image
image = Image.open(BytesIO(screenshot_bytes))
print(image.format, image.size, image.mode)
thumbnail = image.copy()
thumbnail.thumbnail((800, 800))
out = BytesIO()
thumbnail.save(out, format="WEBP", quality=80)
thumbnail_bytes = out.getvalue()
Pillow reads from a memory buffer, so neither the original nor the resized image requires a temporary file.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
Return bytes from a web endpoint
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/preview")
def preview():
# Create screenshot_bytes before this return in your browser lifecycle.
return Response(content=screenshot_bytes, media_type="image/png")
In a real service, create and close browser contexts per workload policy, enforce URL allow-lists, and set request timeouts. Never let an untrusted URL turn your screenshot endpoint into an unrestricted server-side request proxy.
Reliability and performance considerations
- Reuse deliberately: launching a browser is expensive. A long-running worker can reuse a browser while creating isolated contexts or pages for jobs. Close pages and contexts after each job to prevent state and memory growth.
- Limit concurrency: many full-page or high-resolution captures can consume substantial CPU and RAM. Use a bounded queue rather than starting unlimited tasks.
- Set timeouts: navigation, selector waits, and screenshot operations should have explicit limits. Record the URL, viewport, format, and failure type in job logs.
- Control state: use a fresh context when cookies, local storage, authentication, timezone, or geolocation could affect the image. Reusing a context is faster but risks cross-request state leakage.
- Reduce output size: choose
scale="css", JPEG/WebP, a smaller viewport, or an element capture when the consumer does not need a full-resolution page. - Lazy content: full-page capture does not guarantee that an application’s scroll-triggered requests have completed. Scroll or wait on the application’s own completion signal.
Common failures and fixes
“The screenshot is saved nowhere”
That is expected when path is omitted. Keep the returned bytes, write them yourself with open(..., "wb"), or return them from your service.
Executable doesn't exist
The Python package is installed but its browser binary is not. Run python -m playwright install chromium in the same environment used by the application. In a container, install the required system dependencies as documented for your base image.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsTimeout while navigating or waiting
The site may be slow, blocked, or waiting on a resource that never completes. Use a realistic timeout, wait for a stable selector instead of network idle when long-lived connections exist, and capture diagnostic logs. Do not simply increase the timeout indefinitely.
Blank, partial, or covered content
Wait for the relevant selector, disable or await animations, and inspect overlays such as cookie dialogs or modals. For an element screenshot, confirm that the locator matches the intended element and that another element is not covering it.
Unexpected image size or format
Check the requested type, scale, viewport, device descriptor, and browser version. JPEG ignores transparency, and PNG ignores quality. WebP availability depends on the installed Playwright version.
Async runtime errors
Use async_playwright and await every browser operation inside the event loop. If your framework already owns the loop, expose an async handler rather than calling asyncio.run() inside it.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
Or skip the browser setup
ScreenshotNeo provides a website screenshot API when you want a single HTTP request instead of managing Playwright browsers. The endpoint returns PNG, JPEG, WebP, or PDF data, and its cleanup steps accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status.
Call it from Python like this (see the ScreenshotNeo documentation for parameters and response details):
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
If you prefer the command line:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Or use 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 supports full-page and element capture, dark mode, device presets, retina scale, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, selectable cache TTLs, signed public-image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
The Free plan includes 1,000 shots per month without a card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Which approach should you use?
- Use Playwright when the browser is already part of your Python application and you need in-process control over navigation, authentication, DOM locators, or custom browser logic.
- Use a service endpoint when you want to avoid browser installation and lifecycle management, need an HTTP or MCP interface, or are processing screenshots from workers in different languages.
- Use viewport capture for a visual snapshot,
full_page=Truefor a document-length image, and a locator screenshot for a component.
Frequently Asked Questions
Does an in-memory screenshot have to be PNG?
No. PNG is the default, but Playwright can request JPEG or WebP with the type option. JPEG does not support transparent backgrounds, and quality does not affect PNG.
Can I capture an element without first taking a page screenshot?
Yes. Call page.locator("selector").screenshot() (or await it in async code). Playwright scrolls the element into view and waits for actionability.
How do I prove that my code is not writing screenshots to disk?
Omit path and inspect the return value. It is a bytes object; any file creation would have to come from code you add yourself.
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.

