Updated February 2026 · 10 min read

Website Screenshot API
for Python

Need to capture website screenshots in Python? There are three main approaches: run a headless browser with Selenium or Playwright, or call an API like GrabShot. Here's working code for each, with the tradeoffs that matter.

1. Selenium + ChromeDriver

Selenium is the most popular browser automation library in Python. You need Chrome and ChromeDriver installed on your machine.

pip install selenium webdriver-manager
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(url: str, output: str = "screenshot.png"):
    options = Options()
    options.add_argument("--headless=new")
    options.add_argument("--no-sandbox")
    options.add_argument("--window-size=1440,900")
    
    driver = webdriver.Chrome(
        service=Service(ChromeDriverManager().install()),
        options=options
    )
    
    try:
        driver.get(url)
        driver.save_screenshot(output)
        print(f"Saved to {output}")
    finally:
        driver.quit()

screenshot("https://github.com")

Full-page screenshot (scrolls the entire page):

def full_page_screenshot(url: str, output: str = "full.png"):
    options = Options()
    options.add_argument("--headless=new")
    options.add_argument("--no-sandbox")
    
    driver = webdriver.Chrome(
        service=Service(ChromeDriverManager().install()),
        options=options
    )
    
    try:
        driver.set_window_size(1440, 900)
        driver.get(url)
        
        # Get total page height
        height = driver.execute_script(
            "return Math.max(document.body.scrollHeight, "
            "document.documentElement.scrollHeight)"
        )
        driver.set_window_size(1440, height)
        driver.save_screenshot(output)
    finally:
        driver.quit()

Pros: Free, mature ecosystem, tons of Stack Overflow answers.
Cons: ChromeDriver version mismatches are constant pain. Uses 300-500MB RAM per instance. Slow startup (2-5 seconds). Hard to deploy on serverless.

2. Playwright for Python

Microsoft's Playwright has first-class Python support and handles browser management for you. No more ChromeDriver version hell.

pip install playwright
playwright install chromium
from playwright.sync_api import sync_playwright

def screenshot(url: str, output: str = "screenshot.png"):
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page(viewport={"width": 1440, "height": 900})
        page.goto(url, wait_until="networkidle")
        page.screenshot(path=output)
        browser.close()

screenshot("https://github.com")

# Full page? Just add full_page=True:
# page.screenshot(path="full.png", full_page=True)

Async version (for FastAPI, Django async views, etc.):

import asyncio
from playwright.async_api import async_playwright

async def screenshot(url: str, output: str = "screenshot.png"):
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page(viewport={"width": 1440, "height": 900})
        await page.goto(url, wait_until="networkidle")
        await page.screenshot(path=output)
        await browser.close()

asyncio.run(screenshot("https://github.com"))

Pros: Better auto-waiting than Selenium, no driver mismatch issues, async support, multi-browser.
Cons: Still needs a browser installed (~400MB). Still uses significant RAM per instance. Still hard on serverless.

3. GrabShot API (No Browser Needed)

If you just need screenshots (not browser interaction), an API call is simpler than running Chrome. GrabShot handles the browser infrastructure so you don't have to.

# No special dependencies - just requests (or use urllib)
pip install requests
import requests

def screenshot(url: str, output: str = "screenshot.webp"):
    response = requests.get(
        "https://grabshot.dev/v1/screenshot",
        params={
            "url": url,
            "format": "webp",
            "width": "1440",
            "apiKey": "YOUR_API_KEY"  # Free at grabshot.dev
        }
    )
    response.raise_for_status()
    
    with open(output, "wb") as f:
        f.write(response.content)
    
    print(f"Saved {len(response.content)} bytes to {output}")

screenshot("https://github.com")

With device frames and AI cleanup:

def fancy_screenshot(url: str, output: str = "mockup.png"):
    """Screenshot with MacBook frame, cookie banners removed by AI"""
    response = requests.get(
        "https://grabshot.dev/v1/screenshot",
        params={
            "url": url,
            "format": "png",
            "width": "1440",
            "deviceFrame": "macbook-air",
            "aiCleanup": "true",
            "apiKey": "YOUR_API_KEY"
        }
    )
    response.raise_for_status()
    
    with open(output, "wb") as f:
        f.write(response.content)

fancy_screenshot("https://stripe.com")

Batch screenshots (async for speed):

import asyncio
import aiohttp

async def batch_screenshots(urls: list[str], api_key: str):
    async with aiohttp.ClientSession() as session:
        tasks = []
        for url in urls:
            task = session.get(
                "https://grabshot.dev/v1/screenshot",
                params={"url": url, "format": "webp", "apiKey": api_key}
            )
            tasks.append(task)
        
        responses = await asyncio.gather(*tasks)
        
        for i, resp in enumerate(responses):
            data = await resp.read()
            with open(f"screenshot_{i}.webp", "wb") as f:
                f.write(data)
            print(f"Saved {urls[i]}")

urls = [
    "https://github.com",
    "https://stripe.com",
    "https://vercel.com",
]
asyncio.run(batch_screenshots(urls, "YOUR_API_KEY"))

Pros: No Chrome/browser to install. Works on any platform (AWS Lambda, Google Cloud Functions, Raspberry Pi). AI removes cookie popups. Device frame mockups built in. 25 free screenshots/month.
Cons: Paid plans start at $9/mo for 2,500 screenshots. Can't interact with the page (click, scroll, type).

Comparison

Feature Selenium Playwright GrabShot API
pip install + first screenshot5-10 min3-5 min30 seconds
Needs Chrome/browserYesYesNo
RAM per screenshot300-500MB200-400MB~1MB (HTTP call)
Serverless (Lambda, Cloud Functions)PainfulPainfulEasy
Full-page screenshotsManual resizeBuilt-inBuilt-in
Device frame mockupsNoNoYes
Cookie popup removalManual scriptingManual scriptingAI-powered
Page interactionFullFullNo

See it in action

Try GrabShot right now — paste any URL and get a screenshot instantly. No signup needed.

Try Free Screenshot Tool →