Skip to main content

Official Python SDK for SnapRender Screenshot API

Project description

snaprender

PyPI version PyPI downloads license

Official Python SDK for the SnapRender Screenshot API. Capture pixel-perfect screenshots, extract page content, run batch jobs, and manage webhooks with a single library.

500 free screenshots/month. Get your API key

Features

  • Multiple output formats : PNG, JPEG, WebP, and PDF
  • Three input modes : URL, raw HTML, or Markdown
  • Signed URLs : generate pre-signed screenshot URLs (no API key needed at render time)
  • Content extraction : pull Markdown, plain text, HTML, article, links, or metadata from any page
  • Batch screenshots : capture up to 50 URLs in a single job
  • Webhooks : receive real-time notifications for screenshot and quota events
  • Device emulation : iPhone, iPad, Pixel, and more presets
  • Dark mode : capture pages with prefers-color-scheme: dark
  • Ad blocking : remove ads automatically before capture
  • Cookie banner removal : clean screenshots without consent popups
  • Smart caching : configurable CDN cache with TTL control
  • Full-page captures : screenshot the entire scrollable page

Install

pip install snaprender

Quick Start

from snaprender import SnapRender

snap = SnapRender(api_key="sk_live_...")

# Capture by URL
image = snap.capture("https://example.com")
with open("screenshot.png", "wb") as f:
    f.write(image)

# Capture from raw HTML
image = snap.capture(html="<h1>Hello World</h1>")

# Capture from Markdown
image = snap.capture(markdown="# Hello World\nSome **bold** text.")

Cache is OFF by default. Every request captures a fresh screenshot. To save credits on repeated requests, pass cache=True. Cached hits are free and return in under 200ms:

image = snap.capture("https://example.com", cache=True)

Context Manager

with SnapRender(api_key="sk_live_...") as snap:
    image = snap.capture("https://example.com")

The HTTP connection is closed automatically when the block exits.

API Reference

Constructor

SnapRender(api_key, base_url="https://app.snap-render.com", timeout=60.0)
Parameter Type Default Description
api_key str (required) Your SnapRender API key (sk_live_...)
base_url str "https://app.snap-render.com" API base URL
timeout float 60.0 Request timeout in seconds

snap.capture(url, *, html, markdown, **options) -> bytes | dict

Take a screenshot. Provide exactly one of url, html, or markdown.

  • When url is provided alone, the request is sent as GET with query parameters.
  • When html or markdown is provided, the request is sent as POST with a JSON body.
  • Returns raw image bytes by default. Set response_type="json" to get a dict with metadata and a base64 data URI.
# URL with options
jpg = snap.capture(
    "https://example.com",
    format="jpeg",
    width=1920,
    height=1080,
    full_page=True,
    dark_mode=True,
    quality=95,
)

# HTML input
png = snap.capture(html="<h1 style='color:red'>Red Title</h1>", width=800)

# Markdown input
png = snap.capture(markdown="# Report\n\n| Col A | Col B |\n|-------|-------|\n| 1 | 2 |")

# JSON response (base64 data URI + metadata)
result = snap.capture("https://example.com", response_type="json")
print(result["image"])  # data:image/png;base64,...

Options

Option Type Default Description
url str None URL to capture
html str None Raw HTML to render
markdown str None Markdown to render
format str "png" "png", "jpeg", "webp", or "pdf"
width int 1280 Viewport width in pixels
height int 800 Viewport height in pixels
full_page bool False Capture the full scrollable page
quality int 90 JPEG/WebP quality (1-100)
delay int 0 Wait (ms) after page load before capture
dark_mode bool False Emulate dark color scheme
block_ads bool True Block ad networks
block_cookie_banners bool True Remove cookie consent banners
device str None Device preset: "iphone_14", "iphone_15_pro", "pixel_7", "ipad_pro", "macbook_pro"
hide_selectors str None Comma-separated CSS selectors to hide
click_selector str None CSS selector to click before capture
user_agent str None Custom user-agent string
cache bool False Return cached result if available. Off by default: set True to enable caching. Cached hits are free but may be up to 24h old.
cache_ttl int 86400 Cache lifetime in seconds (default 24h). Cached screenshots older than this are recaptured.
response_type str None Set to "json" for metadata + base64 data URI

snap.sign(url, *, expires_in, **options) -> dict

Generate a signed URL that can be used without an API key. Signing itself is free and does not count against your quota. One credit is consumed when the signed URL is rendered.

result = snap.sign(
    "https://example.com",
    expires_in=3600,       # optional, seconds until expiry
    format="png",
    width=1280,
    dark_mode=True,
)
print(result["signed_url"])   # use this in <img> tags, emails, etc.
print(result["expires_at"])   # ISO 8601 timestamp

Options

Option Type Default Description
url str (required) URL to capture
expires_in int None Seconds until the signed URL expires
format str None "png", "jpeg", "webp", or "pdf"
width int None Viewport width
height int None Viewport height
full_page bool None Full-page capture
quality int None JPEG/WebP quality
delay int None Wait (ms) after load
dark_mode bool None Emulate dark mode
block_ads bool None Block ads
block_cookie_banners bool None Remove cookie banners
hide_selectors str None CSS selectors to hide
click_selector str None CSS selector to click
device str None Device preset
user_agent str None Custom user-agent

Returns { "signed_url": str, "expires_at": str, "expires_in": int }


snap.extract(url, *, type, **options) -> dict

Extract content from a web page. Six extraction types are available:

Type Description
"markdown" Page content converted to Markdown (default)
"text" Plain text, all tags stripped
"html" Cleaned HTML
"article" Article body extracted via Readability
"links" All links on the page
"metadata" Title, description, Open Graph tags, etc.
# Extract as Markdown
result = snap.extract("https://example.com", type="markdown")
print(result["content"])
print(result["wordCount"])

# Extract just the article body
article = snap.extract("https://example.com/blog/post", type="article")

# Extract metadata
meta = snap.extract("https://example.com", type="metadata")

# Scope extraction to a specific element
result = snap.extract(
    "https://example.com",
    type="text",
    selector="#main-content",
    max_length=5000,
)

Options

Option Type Default Description
url str (required) URL to extract from
type str "markdown" Extraction type (see table above)
selector str None CSS selector to scope extraction
block_ads bool None Block ads before extraction
block_cookie_banners bool None Remove cookie banners
delay int None Wait (ms) after page load
max_length int None Truncate content to this many characters
cache bool None Return cached extraction if available. Off by default: set True to enable caching. Cached hits are free but may be stale.
cache_ttl int None Cache lifetime in seconds (default 24h).

Returns { "url": str, "type": str, "content": ..., "wordCount": int, "processingTimeMs": int }


snap.batch(urls, **options) -> dict

Create a batch screenshot job for 1 to 50 URLs. The call returns immediately with a job ID. Each URL consumes one credit; credits for failed URLs are rolled back.

job = snap.batch(
    ["https://example.com", "https://example.org", "https://example.net"],
    format="png",
    width=1280,
    dark_mode=True,
)
print(job["job_id"])  # use this to poll status

Options: same screenshot options as capture() (except url, html, markdown, response_type, cache, cache_ttl). These options apply to every URL in the batch.

Returns { "job_id": str, "status": str, "total": int, ... }


snap.get_batch_status(job_id) -> dict

Poll the status of a batch job. Keep polling until status is "completed" or "failed".

import time

job = snap.batch(["https://example.com", "https://example.org"])

while True:
    status = snap.get_batch_status(job["job_id"])
    print(f"{status['status']} - {status.get('completed', 0)}/{status['total']}")
    if status["status"] in ("completed", "failed"):
        break
    time.sleep(2)

# Download results
for result in status["results"]:
    print(result["url"], result["download_url"])

snap.create_webhook(url, events) -> dict

Register a webhook endpoint to receive event notifications. Maximum 5 webhooks per account.

Available events: screenshot.completed, quota.warning, quota.exceeded

webhook = snap.create_webhook(
    url="https://yoursite.com/webhooks/snaprender",
    events=["screenshot.completed", "quota.warning"],
)
print(webhook["id"])
print(webhook["secret"])  # save this for signature verification

snap.list_webhooks() -> list[dict]

List all webhooks registered on your account.

webhooks = snap.list_webhooks()
for wh in webhooks:
    print(wh["id"], wh["url"], wh["events"])

snap.delete_webhook(webhook_id) -> None

Delete a webhook by its ID.

snap.delete_webhook("wh_abc123")

snap.test_webhook(webhook_id) -> dict

Send a test payload to a webhook endpoint. Useful for verifying your handler works before relying on real events.

result = snap.test_webhook("wh_abc123")
print(result)  # delivery status

SnapRender.verify_webhook_signature(payload, signature, secret) -> bool

Static method. Verify the HMAC-SHA256 signature of an incoming webhook payload. Use this in your webhook handler to confirm the request was sent by SnapRender.

from snaprender import SnapRender

# In your webhook handler (e.g., Flask)
@app.route("/webhooks/snaprender", methods=["POST"])
def handle_webhook():
    payload = request.get_data(as_text=True)
    signature = request.headers.get("X-Signature")
    secret = "whsec_..."  # from create_webhook response

    if not SnapRender.verify_webhook_signature(payload, signature, secret):
        return "Invalid signature", 403

    event = request.get_json()
    print(event["type"], event["data"])
    return "OK", 200

snap.info(url) -> dict

Check if a screenshot is cached for a given URL, without capturing it. No credits are consumed.

info = snap.info("https://example.com")
print(info["cached"])      # True or False
print(info["expires_at"])  # ISO timestamp (when cached)

Returns { "url": str, "cached": bool, "cache_key": str | None, "cached_at": str | None, "expires_at": str | None, "content_type": str | None }


snap.usage() -> dict

Get the current billing period's usage summary.

usage = snap.usage()
print(f"{usage['used']}/{usage['limit']} screenshots used")
print(f"Plan: {usage['plan']}, Remaining: {usage['remaining']}")

Returns { "plan": str, "used": int, "limit": int, "remaining": int, "period": dict }


snap.usage_daily(days=30) -> dict

Get a day-by-day usage breakdown.

daily = snap.usage_daily(days=7)
for day in daily["daily"]:
    print(day["date"], day["count"])
Parameter Type Default Description
days int 30 Number of days to include

LangChain Integration

Use SnapRender as a LangChain tool for AI agents:

import os
from langchain_core.tools import tool
from snaprender import SnapRender

client = SnapRender(api_key=os.environ["SNAPRENDER_API_KEY"])

@tool
def take_screenshot(url: str, format: str = "png", dark_mode: bool = False) -> str:
    """Capture a screenshot of any website URL. Returns base64 data URI."""
    result = client.capture(
        url, format=format, dark_mode=dark_mode, response_type="json"
    )
    return result["image"]

Works with LangGraph, CrewAI, and any framework that supports LangChain tools.

Error Handling

All API errors raise SnapRenderError with code, status, and a human-readable message.

from snaprender import SnapRender, SnapRenderError

snap = SnapRender(api_key="sk_live_...")

try:
    snap.capture("https://example.com")
except SnapRenderError as e:
    print(e.code)    # "QUOTA_EXCEEDED"
    print(e.status)  # 429
    print(e)         # "Monthly quota exceeded"

Common error codes: INVALID_API_KEY, QUOTA_EXCEEDED, INVALID_URL, VALIDATION_ERROR, SCREENSHOT_FAILED.

Links

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

snaprender-0.7.2.tar.gz (9.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

snaprender-0.7.2-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file snaprender-0.7.2.tar.gz.

File metadata

  • Download URL: snaprender-0.7.2.tar.gz
  • Upload date:
  • Size: 9.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for snaprender-0.7.2.tar.gz
Algorithm Hash digest
SHA256 5fc220c0f2d9fad5682b09f2eb7c5cf7adea67a7b076877b3907cc4b7193349a
MD5 716f0e076c49f22a4934c1c921a68f9f
BLAKE2b-256 9c554d9c9b1b4aaaefda67c01d1aff7a1040209cb8f6f82df300b32d5d20802c

See more details on using hashes here.

File details

Details for the file snaprender-0.7.2-py3-none-any.whl.

File metadata

  • Download URL: snaprender-0.7.2-py3-none-any.whl
  • Upload date:
  • Size: 10.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for snaprender-0.7.2-py3-none-any.whl
Algorithm Hash digest
SHA256 60d2025919896331d272026a416977b61c56c4374170b91c549d6f99b44c2be6
MD5 b3872643c5492ea5cc9d7a4b2a7c6356
BLAKE2b-256 42fed5cdf931c81cd8b9681cf48743bc9a6ee245bbb967b2cf3bddf2d90861b7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page