Use Playwright’s Python API to open each project URL at a consistent viewport and save a screenshot as an image. For a compact portfolio grid, start with viewport captures; use full-page screenshots when the whole page matters more than a uniform card shape. The examples below use Playwright’s synchronous API, with options for element captures, device scale, and repeatability.
Set up Playwright for Python
Install Playwright and its browser binaries in the Python environment where you will run the capture script:
python -m pip install playwright
python -m playwright install chromium
The examples use Chromium and Playwright’s synchronous Python API. Playwright also offers an asynchronous API; use that when it fits an existing asyncio application. See the official Getting started – Library guide for both API styles.
Generate a batch of portfolio thumbnails
Save the following as make_thumbnails.py. Replace the sample project URLs with your own. It creates an output directory, opens one browser, and saves one viewport screenshot per URL.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →#1 Best Overall
from pathlib import Path
from urllib.parse import urlparse
from playwright.sync_api import sync_playwright
PROJECTS = [
"https://example.com/",
"https://example.org/",
]
OUTPUT_DIR = Path("thumbnails")
VIEWPORT = {"width": 1440, "height": 900}
def filename_for(url: str) -> str:
host = urlparse(url).netloc or "project"
safe_host = "".join(c if c.isalnum() or c in "-." else "_" for c in host)
return f"{safe_host}.png"
def main() -> None:
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context(viewport=VIEWPORT, device_scale_factor=1)
page = context.new_page()
for url in PROJECTS:
try:
response = page.goto(url, wait_until="load", timeout=30_000)
if response is not None and response.status >= 400:
print(f"HTTP {response.status}: {url}")
continue
page.screenshot(path=str(OUTPUT_DIR / filename_for(url)))
print(f"Saved {url}")
except Exception as exc:
print(f"Could not capture {url}: {exc}")
context.close()
browser.close()
if __name__ == "__main__":
main()
Run it with python make_thumbnails.py. The default page.screenshot() captures the current viewport. The explicit viewport gives each project the same CSS-pixel rendering area; choose dimensions that match how your portfolio cards will display the images.
Choose the capture that fits the portfolio
Viewport or full page
A viewport capture is usually the more practical starting point for a grid because each image has a predictable height. To capture the entire scrollable page instead, change the screenshot call to:
page.screenshot(path=str(OUTPUT_DIR / filename_for(url)), full_page=True)
A full-page capture is tall, so it may work better as project documentation or a detail-page preview than as a compact portfolio card. Playwright documents both viewport and full-page screenshots in its Screenshots guide.
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Whole page or one element
If the page contains a specific project preview, capture that matching element with a locator instead of the entire page:
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorspreview = page.locator(".project-preview")
preview.screenshot(path="thumbnails/project-preview.png")
Replace .project-preview with a selector that exists on the target site. A locator screenshot scrolls the element into view. If the matched element is a scrollable container, its screenshot includes only the content currently scrolled into view; it does not automatically expand the container to show all its contents. See the Locator API.
CSS-pixel or device-pixel scale
For locator screenshots, scale="css" produces one output pixel per CSS pixel. scale="device" follows the device scale factor, which can create a higher-resolution image. Select the one that suits the intended display size and file-size needs:
Rank #3
preview.screenshot(path="thumbnails/preview.png", scale="css")
Playwright’s browser context also accepts a device_scale_factor; selected device profiles can be loaded from Playwright’s device registry. Use a viewport and device profile that represent the rendering target you want, rather than assuming one setting suits every portfolio. The official Emulation guide describes device and viewport emulation.
PNG, JPEG, or WebP
Locator screenshots document PNG, JPEG, and WebP output. PNG is lossless; JPEG and WebP accept a quality setting, while PNG does not. Choose based on visual detail, destination support, and file size rather than treating one format as universally best:
preview.screenshot(path="thumbnails/preview.webp", type="webp", quality=80)
The format and quality options are documented in the Locator API. WebP support is version-sensitive: Playwright’s release notes describe its introduction in Python version 1.62. Check the release notes and installed version when relying on it.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Make repeated captures more consistent
Pages can change between visits because of animation, rotating content, timestamps, consent dialogs, or other dynamic elements. Playwright offers locator screenshot options to disable CSS animations and apply a screenshot stylesheet. For example:
preview.screenshot(
path="thumbnails/preview.png",
animations="disabled",
style=".timestamp, .rotating-banner { visibility: hidden !important; }",
)
Use selectors that are appropriate for the page and the portfolio’s editorial purpose. Screenshot styling can control selected page elements, but it does not guarantee identical rendering across sites or visits.
Save image bytes for later processing
If you omit path, Playwright returns the screenshot as bytes. This is useful when another part of your script will process or store the image:
Free tools Windows power users keep installed
One-click scans. No signup required.
Best Value
image_bytes = page.screenshot(full_page=False)
Path("thumbnails/capture.png").write_bytes(image_bytes)
The screenshot documentation covers saving to a path, returning bytes, and full-page capture: Playwright Screenshots.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshoot common capture problems
- The browser executable is missing: install the browser binaries for the environment with
python -m playwright install chromium. If you use a different engine, install that browser instead. - Navigation times out: check that the URL is reachable from the machine running the script and increase the navigation timeout if the site is legitimately slow. A page that never finishes loading may need a different navigation wait condition or a site-specific readiness check.
- The screenshot is blank or incomplete: confirm navigation succeeded and that the site has finished rendering the content you need. Some pages render substantial content after the initial load; wait for a relevant locator or a deliberate delay when necessary.
- The element selector matches nothing: inspect the page’s markup and use a selector that identifies the intended element. Locator screenshots require a matching element.
- The result is too tall for a card: use a viewport screenshot instead of
full_page=True, or capture a specific element. - Images look soft or files are large: choose CSS or device scale based on the displayed size, and select PNG, JPEG, or WebP according to detail and compression requirements.
- Captures vary between runs: disable animations or apply screenshot styling to known dynamic regions. This can reduce some variation but cannot make every site deterministic.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF; its capture options include full-page screenshots and CSS-selector element capture.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for setup and request options. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture by default; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up free for 1,000 screenshots a month, with no card required.
Frequently Asked Questions
Can I capture a mobile version of a project site?
Yes. Create a browser context with a selected Playwright device profile or set a mobile-sized viewport and device scale factor, then capture the page.
Does a full-page screenshot include every item in a scrollable inner panel?
No. A full-page page capture covers the page’s scrollable document; a locator screenshot of a scrollable container shows only the content currently scrolled into view.
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.




