How to Take Website Screenshots in Python
There are three real ways to programmatically capture website screenshots in Python. Each has a different weight class — from heavyweight browser automation to a four-line API call. Here's the code for all three, with the trade-offs laid out honestly.
Selenium + Chrome
Selenium is the original browser automation tool. It launches a real Chrome instance, navigates to the page, and captures the viewport. It works, but it's heavy — you need Chrome installed, a matching ChromeDriver version, and enough RAM to run a full browser.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1280,800")
driver = webdriver.Chrome(options=options)
driver.get("https://example.com")
driver.save_screenshot("screenshot.png")
driver.quit()Watch out for:
- ChromeDriver version mismatches after browser updates
- No native full-page screenshot — viewport capture only
- Requires
pip install seleniumplus a system-level Chrome install - Memory-heavy in CI/CD environments (2GB+ RAM)
Playwright for Python
Playwright is Microsoft's modern alternative. It bundles its own browser binaries, auto-waits for content to render, and has native full_page=True support. It's the best self-hosted option — but you still need to manage browser processes and deal with the ~400MB browser download.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={"width": 1280, "height": 800})
page.goto("https://example.com")
page.screenshot(path="screenshot.png", full_page=True)
browser.close()Better than Selenium, but still:
- 400MB browser download on first install
- Browser process management in production
- Cloudflare and bot-protection sites will block it
- Not great for serverless — cold starts are brutal
SnapRender API (4 lines)
No browser to install, no driver to manage, no process to babysit. Send a POST request with the URL, get back the screenshot as binary. Works from any Python environment — serverless, CI/CD, notebooks, cron jobs.
import requests
response = requests.post(
"https://api.snaprender.dev/v1/screenshot",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"url": "https://example.com"}
)
with open("screenshot.png", "wb") as f:
f.write(response.content)That's the entire working script. pip install requests is likely already in your environment.
Full-page screenshots, custom viewports, JPEG quality
Most screenshot use cases need more than a basic viewport capture. Here's how to get a full-page screenshot at a specific resolution with JPEG compression:
# Full-page screenshot with custom viewport + JPEG quality
response = requests.post(
"https://api.snaprender.dev/v1/screenshot",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"url": "https://example.com",
"full_page": True,
"viewport": {"width": 1440, "height": 900},
"format": "jpeg",
"quality": 85
}
)| Parameter | Type | Description |
|---|---|---|
| full_page | boolean | Capture entire scrollable page, not just the viewport |
| viewport | object | Set width and height in pixels (default 1280x800) |
| format | string | "png" or "jpeg" (default png) |
| quality | integer | JPEG quality 1-100 (default 80, ignored for PNG) |
Saving to file, uploading to S3, processing with PIL
Once you have the screenshot bytes, you can pipe them anywhere. Here are the two most common follow-up steps:
Upload to S3
Capture and archive screenshots directly to an S3 bucket — useful for monitoring, compliance, or building a visual diff pipeline.
import requests
import boto3
# 1. Take the screenshot
response = requests.post(
"https://api.snaprender.dev/v1/screenshot",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"url": "https://example.com"}
)
# 2. Upload to S3
s3 = boto3.client("s3")
s3.put_object(
Bucket="my-screenshots",
Key="captures/example.png",
Body=response.content,
ContentType="image/png"
)Process with PIL / Pillow
Resize, crop, or watermark screenshots on the fly. The response bytes work directly with Pillow's Image.open().
from PIL import Image
from io import BytesIO
import requests
response = requests.post(
"https://api.snaprender.dev/v1/screenshot",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"url": "https://example.com", "format": "png"}
)
img = Image.open(BytesIO(response.content))
img = img.resize((640, 400)) # resize
img = img.crop((0, 0, 640, 300)) # crop
img.save("thumbnail.png")Skip the browser setup
100 free screenshots per month. No browser to install. No credit card.
Get your API keyFrequently asked questions
The easiest way is using a screenshot API like SnapRender. It takes 4 lines of Python code with the requests library — no browser installation or driver management required.
Yes. Selenium requires scrolling hacks, Playwright has a full_page=True parameter, and SnapRender supports full_page in the API request body. All three methods work, but API-based approaches are the most reliable for very long pages.
You need a headless browser. Selenium and Playwright both run real browsers. SnapRender runs a managed browser in the cloud that waits for JavaScript to finish before capturing.
Playwright is generally better — it has a simpler API, auto-waits for content, and supports full-page screenshots natively. Selenium requires more boilerplate and manual waits.
Standard headless browsers get blocked by Cloudflare. SnapRender has built-in Cloudflare bypass via FlareSolverr — just add use_flaresolverr: true to your request.