Screenshot -- Python SDK
Official Python SDK for the Nodium Screenshot API. Supports Python 3.9+ with both synchronous and asynchronous interfaces.
Installation
bash
pip install nodium-screenshotbash
# or with poetry
poetry add nodium-screenshot
# with async support (installs httpx)
pip install nodium-screenshot[async]Quick Start
python
from nodium_screenshot import NodiumScreenshot
client = NodiumScreenshot("YOUR_API_KEY")
result = client.take(
url="https://example.com",
format="png",
)
with open("screenshot.png", "wb") as f:
f.write(result.data)Client Initialization
python
from nodium_screenshot import NodiumScreenshot
# Basic initialization
client = NodiumScreenshot("YOUR_API_KEY")
# With options
client = NodiumScreenshot(
api_key="YOUR_API_KEY",
base_url="https://api.nodium.io/api/v1/screenshot",
timeout=60, # Request timeout in seconds (default: 60)
retries=3, # Automatic retries on 5xx errors (default: 3)
retry_delay=1.0, # Base delay between retries in seconds (default: 1.0)
)Environment Variable
python
import os
os.environ["NODIUM_API_KEY"] = "YOUR_API_KEY"
# Reads from NODIUM_API_KEY automatically
client = NodiumScreenshot()Synchronous Usage
take() -- Capture a Screenshot
python
result = client.take(
url="https://example.com",
format="png",
viewport_width=1280,
viewport_height=1024,
full_page=True,
image_quality=90,
)
# result.data -- bytes with image/PDF content
# result.headers -- dict with response headers
with open("screenshot.png", "wb") as f:
f.write(result.data)animate() -- Record an Animated Screenshot
python
result = client.animate(
url="https://example.com",
format="mp4",
scroll_animation="smooth",
animation_duration=5,
viewport_width=1280,
viewport_height=720,
)
with open("animation.mp4", "wb") as f:
f.write(result.data)bulk() -- Batch Capture
python
results = client.bulk(
urls=[
"https://example.com",
"https://example.org",
"https://example.net",
],
format="png",
viewport_width=1280,
viewport_height=1024,
)
for i, result in enumerate(results):
with open(f"screenshot-{i}.png", "wb") as f:
f.write(result.data)get_usage() -- Check API Usage
python
usage = client.get_usage()
print(f"Screenshots taken: {usage.screenshots_taken}")
print(f"Monthly limit: {usage.monthly_limit}")
print(f"Remaining: {usage.remaining}")
print(f"Billing period ends: {usage.period_end}")Async Usage
The SDK provides an async client powered by httpx for non-blocking I/O.
python
from nodium_screenshot import AsyncNodiumScreenshot
client = AsyncNodiumScreenshot("YOUR_API_KEY")
async def capture():
result = await client.take(
url="https://example.com",
format="png",
)
async with aiofiles.open("screenshot.png", "wb") as f:
await f.write(result.data)
await client.close()Async Context Manager
python
async with AsyncNodiumScreenshot("YOUR_API_KEY") as client:
result = await client.take(
url="https://example.com",
format="png",
)
async with aiofiles.open("screenshot.png", "wb") as f:
await f.write(result.data)Concurrent Captures
python
import asyncio
async def capture_multiple():
async with AsyncNodiumScreenshot("YOUR_API_KEY") as client:
urls = [
"https://example.com",
"https://example.org",
"https://example.net",
]
tasks = [
client.take(url=url, format="png")
for url in urls
]
results = await asyncio.gather(*tasks)
for i, result in enumerate(results):
async with aiofiles.open(f"screenshot-{i}.png", "wb") as f:
await f.write(result.data)
asyncio.run(capture_multiple())Fluent Builder API
Build screenshot requests using a chainable interface.
python
result = (
client.take()
.url("https://example.com")
.format("png")
.viewport(1280, 1024)
.full_page(True)
.image_quality(90)
.execute()
)
with open("screenshot.png", "wb") as f:
f.write(result.data)Builder Methods
| Method | Description |
|---|---|
.url(url) | Target URL to capture |
.html(html) | Raw HTML to render |
.markdown(md) | Markdown content to render |
.format(fmt) | Output format: png, jpeg, webp, avif, pdf, etc. |
.viewport(width, height) | Viewport dimensions |
.viewport_device(device) | Device emulation (e.g. iphone_16_pro) |
.full_page(bool) | Capture the entire scrollable page |
.image_quality(n) | JPEG/WebP quality (1-100) |
.selector(css) | Capture a specific CSS selector |
.delay(ms) | Wait before capture (milliseconds) |
.block_ads(bool) | Block ads and trackers |
.dark_mode(bool) | Force dark color scheme |
.response_type(type) | by_format, json, or empty |
.webhook(url) | Webhook URL for async delivery |
.execute() | Execute the request and return the result |
Async Builder
The async client supports the same fluent API with await:
python
result = await (
client.take()
.url("https://example.com")
.format("png")
.viewport(1440, 900)
.full_page(True)
.execute()
)Error Handling
The SDK raises typed exceptions for all API errors.
python
from nodium_screenshot import NodiumError, NodiumAPIError, NodiumTimeoutError
try:
result = client.take(
url="https://example.com",
format="png",
)
with open("screenshot.png", "wb") as f:
f.write(result.data)
except NodiumAPIError as e:
print(f"Error code: {e.code}") # e.g. "request_not_valid"
print(f"Message: {e.message}") # Human-readable description
print(f"HTTP status: {e.http_status}") # e.g. 400
print(f"Retryable: {e.is_retryable}") # True for 5xx errors
if e.code == "screenshots_limit_reached":
print("Monthly quota exceeded. Upgrade your plan.")
except NodiumTimeoutError:
print("Request timed out. Try increasing the timeout.")
except NodiumError as e:
# Base exception for all SDK errors
print(f"SDK error: {e}")Signed URL Generation
Generate pre-signed URLs for safe sharing without exposing your API key.
python
signed_url = client.generate_signed_url(
url="https://example.com",
format="png",
viewport_width=1280,
viewport_height=1024,
expires_in=3600, # Valid for 1 hour
)
print(signed_url)
# https://api.nodium.io/api/v1/screenshot/take?url=...&signature=...&expires=...Embed in HTML
python
signed_url = client.generate_signed_url(
url="https://example.com",
format="png",
expires_in=300,
)
html = f'<img src="{signed_url}" alt="Screenshot" />'Django Integration
Settings
python
# settings.py
NODIUM_API_KEY = os.environ.get("NODIUM_API_KEY")View Example
python
# views.py
from django.http import HttpResponse, JsonResponse
from django.conf import settings
from nodium_screenshot import NodiumScreenshot, NodiumAPIError
client = NodiumScreenshot(settings.NODIUM_API_KEY)
def capture_screenshot(request):
url = request.GET.get("url")
if not url:
return JsonResponse({"error": "url parameter required"}, status=400)
try:
result = client.take(url=url, format="png", viewport_width=1280, viewport_height=1024)
response = HttpResponse(result.data, content_type="image/png")
response["Content-Disposition"] = 'inline; filename="screenshot.png"'
return response
except NodiumAPIError as e:
return JsonResponse(
{"error": e.code, "message": e.message},
status=e.http_status,
)Flask Integration
python
from flask import Flask, request, Response, jsonify
from nodium_screenshot import NodiumScreenshot, NodiumAPIError
app = Flask(__name__)
client = NodiumScreenshot(os.environ["NODIUM_API_KEY"])
@app.route("/screenshot")
def screenshot():
url = request.args.get("url")
if not url:
return jsonify(error="url parameter required"), 400
try:
result = client.take(url=url, format="png")
return Response(result.data, mimetype="image/png")
except NodiumAPIError as e:
return jsonify(error=e.code, message=e.message), e.http_statusFull Example
A complete example that captures a screenshot, saves it to disk, and handles errors.
python
import os
import sys
from pathlib import Path
from nodium_screenshot import NodiumScreenshot, NodiumAPIError, NodiumError
def capture_and_save(target_url: str, output_path: str) -> None:
client = NodiumScreenshot(os.environ.get("NODIUM_API_KEY"))
try:
# Check usage before capturing
usage = client.get_usage()
if usage.remaining <= 0:
print("No screenshots remaining this billing period.", file=sys.stderr)
sys.exit(1)
print(f"Remaining quota: {usage.remaining}/{usage.monthly_limit}")
# Take the screenshot using the fluent builder
result = (
client.take()
.url(target_url)
.format("png")
.viewport(1440, 900)
.full_page(True)
.block_ads(True)
.delay(1000)
.image_quality(95)
.execute()
)
# Ensure the output directory exists
Path(output_path).parent.mkdir(parents=True, exist_ok=True)
# Write the screenshot to disk
with open(output_path, "wb") as f:
f.write(result.data)
print(f"Screenshot saved to {output_path}")
print(f"Rendering time: {result.headers['rendering_seconds']}s")
print(f"File size: {result.headers['size_bytes'] / 1024:.1f} KB")
print(f"Reference: {result.headers['reference']}")
except NodiumAPIError as e:
print(f"API error [{e.code}]: {e.message}", file=sys.stderr)
if e.is_retryable:
print("This error is retryable. The SDK already retried automatically.", file=sys.stderr)
sys.exit(1)
except NodiumError as e:
print(f"SDK error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
capture_and_save("https://example.com", "./output/screenshot.png")Next Steps
- API Reference -- Complete reference for all 145+ parameters
- Guides -- Practical guides for common use cases
- Getting Started -- Quick intro and cURL examples