cc.me / Screenshots

Screenshots.

Render any page in a managed headless Chrome and get a PNG back. Every render happens in a fresh, incognito-style browser context that is disposed afterwards, and every request is paid for with a proof-of-work token — no accounts, no API keys. Results are cached for an hour.

Request

GET /shot?token=<token> where the token is a proof of work over the request document described below. The response is image/png; an x-cache: hit header marks answers served from the hour-long cache. GET /shot/config returns the required level as JSON, currently as {"level": …}.

GET /shot?token=eyJ1cmwiOiJodHRwczovL2V4YW1wbGUuY29tLyIsIndpZHRoIjo4MDAsImhlaWdodCI6NjAwLCJzY2FsZSI6MC41LCJ0cyI6MTc1MjYwMDAwMH0.AAAmB0i-4vE

Document

The proof-of-work document is a JSON object with exactly these fields (no extras, any order):

url
http or https page to render. Non-public addresses are refused.
width, height
Render viewport in CSS pixels, integers from 1 to 2048 each.
scale
Optional downscale factor in (0, 1], default 1. The PNG comes back at width×scale by height×scale pixels; Chrome does the scaling.
ts
Current Unix time in seconds. Accepted within 5 minutes either way, so tokens cannot be stockpiled.

Solve to the level from /shot/config — default 24, sized so a GPU pays a few milliseconds and browser workers a few seconds — with any solver from the proof-of-work page:

doc=$(jq -nc --arg url https://example.com/ \
  '{url: $url, width: 800, height: 600, scale: 0.5, ts: now | floor}')
curl -sG https://cc.me/shot --data-urlencode "token=$(node pow.mjs solve 24 "$doc")" -o shot.png

Identical documents (ignoring ts) hit the same cache entry, so retrying within the hour is free for the server and instant for you.

Try it

Solves the proof of work in this page with Web Workers, then requests the screenshot.

Errors

400
Malformed token or document, out-of-range size or scale, stale ts, or a URL pointing at a non-public address.
403
Proof of work below the required level.
502
The page failed to load (DNS, TLS, connection refused…).
503
The managed Chrome is unavailable.
504
The page did not finish loading in time.