Menu
pythontutorialscreenshots

How to Take Website Screenshots in Python (3 Methods)

SnapSharp Team·March 27, 2026·7 min read

How to Take Website Screenshots in Python

Need to capture a webpage as an image from Python? There are three main approaches, each with different trade-offs. This guide walks through all three with working code, then compares them side-by-side.

Method 1: Playwright

Playwright is Microsoft's browser automation library. It ships a bundled Chromium binary and provides a clean async API.

Installation

pip install playwright
playwright install chromium

The playwright install command downloads a Chromium binary (~150 MB). This is a one-time step.

Basic Screenshot

from playwright.sync_api import sync_playwright

def screenshot_playwright(url: str, output: str = "screenshot.png") -> None:
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page(viewport={"width": 1280, "height": 720})
        page.goto(url, wait_until="networkidle")
        page.screenshot(path=output)
        browser.close()

screenshot_playwright("https://example.com")

Full-Page Screenshot

page.screenshot(path="full.png", full_page=True)

Dark Mode

page = browser.new_page(
    viewport={"width": 1280, "height": 720},
    color_scheme="dark",
)

Capture a Specific Element

element = page.query_selector(".hero-section")
if element:
    element.screenshot(path="hero.png")

Pros and Cons

Pros: Full browser fidelity, supports Firefox and WebKit too, excellent async support, actively maintained.

Cons: 150 MB Chromium download, ~200 MB RAM per browser instance, you manage concurrency and process lifecycle, Chrome updates can break scripts.


Method 2: Selenium

Selenium is the oldest browser automation framework. It works with Chrome via ChromeDriver.

Installation

pip install selenium webdriver-manager

webdriver-manager automatically downloads the correct ChromeDriver for your Chrome version.

Basic Screenshot

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

def screenshot_selenium(url: str, output: str = "screenshot.png") -> None:
    options = Options()
    options.add_argument("--headless=new")
    options.add_argument("--window-size=1280,720")
    options.add_argument("--disable-gpu")
    options.add_argument("--no-sandbox")

    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service, options=options)

    try:
        driver.get(url)
        driver.implicitly_wait(5)
        driver.save_screenshot(output)
    finally:
        driver.quit()

screenshot_selenium("https://example.com")

Full-Page Screenshot (Chrome DevTools Protocol)

Selenium does not natively support full-page screenshots in Chrome. You need the CDP workaround:

import base64

def full_page_screenshot_selenium(driver, output: str) -> None:
    metrics = driver.execute_cdp_cmd("Page.getLayoutMetrics", {})
    width = metrics["contentSize"]["width"]
    height = metrics["contentSize"]["height"]

    driver.execute_cdp_cmd("Emulation.setDeviceMetricsOverride", {
        "mobile": False,
        "width": width,
        "height": height,
        "deviceScaleFactor": 1,
    })

    result = driver.execute_cdp_cmd("Page.captureScreenshot", {
        "format": "png",
        "captureBeyondViewport": True,
    })

    with open(output, "wb") as f:
        f.write(base64.b64decode(result["data"]))

Pros and Cons

Pros: Mature ecosystem, huge community, works with Chrome, Firefox, Edge, and Safari.

Cons: ChromeDriver version mismatches are painful, slower than Playwright, full-page capture requires CDP hacks, verbose API.


Method 3: SnapSharp API

The SnapSharp API handles browser rendering in the cloud. You send a URL, get an image back. No local browser needed.

Installation

pip install snapsharp

Basic Screenshot (SDK)

from snapsharp import SnapSharp
import os

snap = SnapSharp(os.environ["SNAPSHARP_API_KEY"])

image = snap.screenshot("https://example.com", width=1280, height=720)
with open("screenshot.png", "wb") as f:
    f.write(image)

Basic Screenshot (raw HTTP)

import os
import requests

API_KEY = os.environ["SNAPSHARP_API_KEY"]

def screenshot_api(url: str, output: str = "screenshot.png", **kwargs) -> None:
    params = {"url": url, "width": 1280, "height": 720, **kwargs}
    response = requests.get(
        "https://api.snapsharp.dev/v1/screenshot",
        params=params,
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    response.raise_for_status()
    with open(output, "wb") as f:
        f.write(response.content)

screenshot_api("https://example.com")

Full-Page + Dark Mode

image = snap.screenshot(
    "https://example.com",
    full_page=True,
    dark_mode=True,
    format="webp",
)

Batch Screenshots with Concurrency

import concurrent.futures

urls = [
    "https://example.com",
    "https://github.com",
    "https://linear.app",
    "https://vercel.com",
]

def capture(url: str) -> str:
    domain = url.split("//")[1].split("/")[0]
    image = snap.screenshot(url, width=1280)
    path = f"{domain}.png"
    with open(path, "wb") as f:
        f.write(image)
    return path

with concurrent.futures.ThreadPoolExecutor(max_workers=5) as pool:
    results = list(pool.map(capture, urls))

Error Handling

from snapsharp import AuthError, RateLimitError, TimeoutError

try:
    image = snap.screenshot("https://example.com")
except AuthError:
    print("Invalid API key")
except RateLimitError as e:
    print(f"Rate limited — retry after {e.retry_after}s")
except TimeoutError:
    print("Page took too long to render")

Pros and Cons

Pros: No local browser, elastic scaling, dark mode / full-page / PDF / element capture built-in, ad blocking, handles Chrome updates for you.

Cons: Requires network access, costs money at scale (100 free/month), adds ~2–4s network latency compared to local capture.


Comparison Table

FeaturePlaywrightSeleniumSnapSharp API
Setuppip install + browser downloadpip install + ChromeDriverpip install snapsharp
Local browser requiredYes (Chromium)Yes (Chrome)No
Full-page captureBuilt-inCDP hackBuilt-in
Dark modecolor_scheme paramManual emulationdark_mode=True
Element captureBuilt-inManual cropselector param
PDF outputBuilt-inLimitedBuilt-in
Ad blockingManual (route interception)Manual (extensions)block_ads=True
ConcurrencyYou manage processesYou manage driversElastic (cloud)
RAM per capture~200 MB~250 MB0 (server-side)
Best forE2E tests, local toolingLegacy projects, cross-browserProduction APIs, serverless

Which Should You Choose?

  • Playwright if you're already running browser tests and want screenshots as a side effect.
  • Selenium if you're locked into an existing Selenium test suite.
  • SnapSharp API if you want zero-ops, serverless-compatible screenshot capture that scales without managing Chrome processes.

All three produce accurate screenshots. The difference is operational: how much infrastructure do you want to own?

Get a free SnapSharp API key →