ShotWolf Python SDK
Official Python client for the ShotWolf API - capture screenshots, render device mockups, generate Open Graph cards, convert HTML to PDF, and run pixel-level visual regression diffs through a single JSON HTTP API.
- Zero dependencies (standard-library only, Python 3.8+)
- Typed (ships
py.typed,TypedDictparams andLiteralenums) - Built-in retries with backoff, idempotency keys, and an async polling helper
Install
pip install shotwolf
Quick start
Get an API key at shotwolf.com/dashboard/api_keys.
from shotwolf import ShotWolf
sw = ShotWolf() # reads SHOTWOLF_API_KEY, or pass ShotWolf("sw_live_...")
shot = sw.capture(url="https://example.com", full_page=True, dismiss_cookies=True)
print(shot["image_url"])
Usage
Screenshots
# Sync - returns the image URL inline (~1-4s)
shot = sw.capture(url="https://stripe.com", device="iphone_15_pro")
# Async - queue and poll (or pass webhook_url for a callback)
queued = sw.capture_async(url="https://stripe.com")
done = sw.wait_for(queued["id"]) # polls until status is done
# Batch - one page, many viewports (cheaper than N calls)
batch = sw.batch(url="https://stripe.com", devices=["default", "iphone_15_pro", "ipad_pro_12_9"])
Device & social mockups
mockup = sw.mockup(url="https://stripe.com", frame="macbook_air", bg="gradient")
Open Graph cards
og = sw.og(template="blog_card", variables={"title": "Ship faster", "author": "Jane Doe"})
HTML / URL to PDF
pdf = sw.pdf(html="<h1>Invoice #42</h1>", page_format="A4", print_background=True)
Visual regression diff
diff = sw.diff(
before_url="https://staging.example.com",
after_url="https://example.com",
ignore_regions=[{"x": 0, "y": 0, "width": 1280, "height": 80}], # mask a dynamic header
)
if not diff["passed"]:
print(f"{diff['diff_ratio'] * 100:.2f}% changed", diff["diff_image_url"])
Account balance
account = sw.account()
print(account["balance_cr"], account["tier"]["name"])
Idempotency
Pass idempotency_key to make money-charging POSTs safe to retry. A repeat with
the same key and body within 24h replays the original response instead of
charging again.
import uuid
sw.capture(url="https://example.com", idempotency_key=str(uuid.uuid4()))
Error handling
Any non-2xx response raises ShotWolfError carrying the API error type, HTTP
status, and message.
from shotwolf import ShotWolfError
try:
sw.capture(url="https://example.com")
except ShotWolfError as err:
if err.type == "insufficient_credits":
... # top up at https://shotwolf.com/pricing
print(err.status, err.type, err.message, err.request_id)
Configuration
sw = ShotWolf(
"sw_live_xxx",
base_url="https://shotwolf.com", # override for self-host / testing
timeout=60.0, # per-request timeout in seconds
max_retries=2, # retries on 429 / 5xx
retry_backoff=0.5, # base backoff, doubled per attempt
)
Retries honor the Retry-After header on 429 responses. 4xx responses
other than 429 are never retried.
API coverage
| Method | Endpoint |
|---|---|
capture(**params) |
POST /api/v1/captures |
capture_async(**params) |
POST /api/v1/captures/async |
batch(**params) |
POST /api/v1/capture/batch |
mockup(**params) |
POST /api/v1/mockups |
og(**params) |
POST /api/v1/og |
pdf(**params) |
POST /api/v1/pdf |
diff(**params) |
POST /api/v1/diffs |
get_screenshot(id) |
GET /api/v1/screenshots/:id |
wait_for(id) |
polls get_screenshot until done/failed |
account() |
GET /api/v1/account |
Full parameter reference: shotwolf.com/docs.
License
MIT
Metadata
Release files for shotwolf 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| shotwolf-0.1.0.tar.gz | 7.6 kB | Without provenance | Details for shotwolf-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| shotwolf-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for shotwolf-0.1.0-py3-none-any.whl |
Total release size: 16.8 kB
Release files / shotwolf-0.1.0.tar.gz
| Download URL | shotwolf-0.1.0.tar.gz |
|---|---|
| Size | 7.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3a569684ea093404e1574975b8c0053e4b7575bd2400af5023f4d46352464fad
|
|
BLAKE2b-256 checksum How to use checksums |
3c4d9aea2a0c803d442c0cd57b7eeb342fcd8b8ff52a975805725bf7d4087a4b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / shotwolf-0.1.0-py3-none-any.whl
| Download URL | shotwolf-0.1.0-py3-none-any.whl |
|---|---|
| Size | 9.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
270bf88a0c83d2d22a9c8010783349075e4173d9df5f8f8a02a12b54b64b3017
|
|
BLAKE2b-256 checksum How to use checksums |
61cd731920743c1ae557b1d00b0707556fc780f395af08684d99c2b8077094a9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Security for shotwolf 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.