How to Take Website Screenshots Programmatically
Sometimes curl isn't enough. You need to see what a page actually renders — complete with lazy-loaded images, JavaScript widgets, and the fold.
The {{screenshot-api}} on Apify captures full-page or viewport screenshots of any URL. Here's how to use it.
Quick Start
import requests, time
API_TOKEN = "YOUR_APIFY_TOKEN"
ACTOR_ID = "weeknds~website-screenshot-api"
resp = requests.post(
f"https://api.apify.com/v2/acts/{ACTOR_ID}/runs",
headers={"Authorization": f"Bearer {API_TOKEN}"},
json={
"url": "https://news.ycombinator.com",
"fullPage": True,
"viewportWidth": 1280,
"viewportHeight": 720
}
)
run_id = resp.json()["data"]["id"]
time.sleep(15)
items = requests.get(
f"https://api.apify.com/v2/acts/{ACTOR_ID}/runs/{run_id}/dataset/items",
headers={"Authorization": f"Bearer {API_TOKEN}"}
).json()
screenshot_url = items[0]["screenshotUrl"]
print(f"Screenshot: {screenshot_url}")
Also works with curl:
curl -X POST "https://api.apify.com/v2/acts/weeknds~website-screenshot-api/runs" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "fullPage": true}'
curl "https://api.apify.com/v2/acts/weeknds~website-screenshot-api/runs/RUN_ID/dataset/items" \
-H "Authorization: Bearer YOUR_TOKEN"
What You Can Configure
url is the only required field. Everything else has sensible defaults.
fullPage defaults to true and captures the entire scrollable page. Set it false for just the viewport.
viewportWidth and viewportHeight default to 1280x720. Good for desktop previews, but bump it up for retina-quality output.
waitUntil defaults to networkidle2, meaning it waits until at most 2 network connections are active for 500ms. This catches most lazy-loaded content. For simpler pages, load or domcontentloaded is faster.
format is png by default. Switch to jpeg with a quality value if file size matters more than crispness.
Real-World Uses
Social Media Preview Generator
Generate Open Graph images by screenshooting a dedicated preview page. Build an HTML template, serve it somewhere, screenshot it at 1200x630. Instant og:image without touching Photoshop.
Daily Website Snapshots
Take a screenshot of your site every day and archive it. When someone asks "when did that change," you have the answer. Pair it with the screenshot comparison tool to get automatic alerts when something shifts.
Competitor Landing Page Archive
Track how competitors update their homepages over time. Screenshot their site weekly and flip through the archive to spot redesigns, new features, or messaging changes.
Handling Lazy-Loaded Content
The networkidle2 wait strategy catches most lazy-loaded images and widgets. For infinite-scroll pages, you can't capture everything in one shot — screenshot individual sections instead.
What It Costs
$0.003 per screenshot. That's 333 screenshots for a dollar. Running your own headless Chrome instance costs more in compute alone — and you still have to deal with proxy rotation, CAPTCHAs, and retry logic. If you're doing anything interesting with screenshots, I'd love to hear about it.
Top comments (0)