Screenshot API with cURL.
Shotium is a hosted screenshot API you drive from any shell with plain curl: no browser on the CI runner, no wrapper scripts around headless Chrome. One command sends a URL and writes back PNG, JPEG or WebP bytes — full-page capture and template-based OG images included.
How do I take a screenshot with curl?
One command. Sign in, create an API key, export it as SHOTIUM_KEY, and this runs as-is:
curl -H "Authorization: Bearer $SHOTIUM_KEY" \
"https://api.shotium.com/v1/screenshot?url=https://example.com&format=png" \
-o shot.png --failFull-page screenshots and viewport control
Set full_page to capture the entire scroll height (up to 20,000px). Quote the whole URL so your shell leaves the ampersands alone:
curl -H "Authorization: Bearer $SHOTIUM_KEY" \
"https://api.shotium.com/v1/screenshot?url=https://news.ycombinator.com&full_page=true&format=webp&quality=90" \
-o page.webp --failGenerate OG images from templates
POST typed parameters into one of five built-in templates and get a finished 1200×630 social card back — perfect for build steps that stamp a card per release:
curl -X POST https://api.shotium.com/v1/og-image \
-H "Authorization: Bearer $SHOTIUM_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "blog",
"params": { "title": "Shipping fast without breaking things", "author": "Ada L." },
"format": "png"
}' -o og.png --failHow do I verify an API key without spending a render?
GET /v1/me validates the key and returns its prefix and name — a health check for CI secrets that costs zero credits:
curl -H "Authorization: Bearer $SHOTIUM_KEY" https://api.shotium.com/v1/me
# 200 → key is valid (prefix + name in the body); 401 → revoked or wrongError handling
With --fail, curl exits non-zero on HTTP errors — right for CI. Drop it to inspect the RFC 9457 problem+json body. Failed renders are never billed:
curl -s -H "Authorization: Bearer $SHOTIUM_KEY" \
"https://api.shotium.com/v1/screenshot?url=https://example.com" \
-w '\nHTTP %{http_code}\n'
# {"type":"rate_limited", ...} → honor Retry-After, then retry
# {"type":"render_timeout", ...} → the site took >30s; retry or skipParameters at a glance
| Param | Default | Notes |
|---|---|---|
url | required | http(s) URL to render |
width / height | 1280 × 800 | Viewport, up to 3840 × 2160 |
full_page | false | Full scroll height, ≤20,000px |
format | png | png | jpeg | webp |
quality | 80 | 1–100, lossy formats only |
Full reference — auth, OG templates, rate limits, error table — in the docs. Template parameters live on /og-templates.
Frequently asked questions
Can I take screenshots from a CI pipeline?
Yes — that's the natural fit. No browser is installed on the runner: one curl command against the API renders the page server-side. Store the API key as a CI secret and use --fail so HTTP errors fail the step.
How do I save the screenshot to a file with curl?
Use -o filename together with --fail. On success the image bytes go to the file; on an HTTP error, --fail makes curl exit non-zero instead of writing the JSON error body into your .png.
How do I debug a failing render?
Drop --fail and add -w with http_code. The body is RFC 9457 problem+json with a stable type field — rate_limited means honor Retry-After; render_timeout means the site took over 30 seconds; blocked_target means the URL resolves to a blocked network range.
Why does my saved file contain JSON instead of an image?
Because curl wrote the error response to it. Without --fail, curl saves whatever the server returned — including the RFC 9457 problem+json error body — into the file named by -o. Always pair -o with --fail so HTTP errors exit non-zero and leave no bogus image behind. Failed renders are never billed.
Try it on your own pages
Sign-up is GitHub OAuth and comes with 100 free render credits — no card. Failed renders never bill. Plans from $15/month on pricing.
Also available for: Python · Node.js · PHP · Ruby · Go · Java