Screenshot API · cURL

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 --fail

Full-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 --fail

Generate 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 --fail

How 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 wrong

Error 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 skip

Parameters at a glance

ParamDefaultNotes
urlrequiredhttp(s) URL to render
width / height1280 × 800Viewport, up to 3840 × 2160
full_pagefalseFull scroll height, ≤20,000px
formatpngpng | jpeg | webp
quality801–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