Shot renders any public URL to a PNG, JPEG or WebP — full page, a single element, ads blocked. No SDK, no browser to manage. Free 20 renders a day, no credit card.
Get a free API key
POST /v1/screenshot.Shot at a glance: POST a URL, get a screenshot back. Free 20 renders a day per key, no credit card. PNG, JPEG or WebP; full page or one element; ads blocked; results cached for 1 hour.
Scrolls the page step by step to trigger lazy loading, then captures the whole document — not just the viewport.
Pass a CSS selector and get only that element — a chart, a card, a hero section.
Trackers and ad networks are blocked by default, so captures are clean and faster.
Repeat renders of the same URL are served from a 1-hour cache. Typical render: under 2 seconds.
Private IPs, localhost, cloud metadata endpoints and redirect tricks are all blocked. No anonymous endpoint.
One endpoint, one Bearer key, image bytes back. JSON metadata mode with Accept: application/json.
POST /v1/screenshot — synchronous, 30 s hard timeout.
curl -X POST https://clioos.com/shot/v1/screenshot \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "full_page": true}' \
--output shot.png
Python
import requests
r = requests.post(
"https://clioos.com/shot/v1/screenshot",
headers={"Authorization": "Bearer YOUR_KEY"},
json={"url": "https://example.com", "full_page": True},
timeout=60,
)
r.raise_for_status()
open("shot.png", "wb").write(r.content)
JavaScript (Node 18+)
const res = await fetch("https://clioos.com/shot/v1/screenshot", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ url: "https://example.com", full_page: true }),
});
if (!res.ok) throw new Error(`Shot failed: ${res.status}`);
const { writeFileSync } = await import("node:fs");
writeFileSync("shot.png", Buffer.from(await res.arrayBuffer()));
Go
package main
import (
"bytes"
"encoding/json"
"net/http"
"os"
)
func main() {
body, _ := json.Marshal(map[string]any{
"url": "https://example.com", "full_page": true,
})
req, _ := http.NewRequest("POST",
"https://clioos.com/shot/v1/screenshot", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer YOUR_KEY")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
panic("Shot failed: " + res.Status)
}
f, _ := os.Create("shot.png")
defer f.Close()
buf := new(bytes.Buffer)
buf.ReadFrom(res.Body)
f.Write(buf.Bytes())
}
| Parameter | Default | Notes |
|---|---|---|
url | — | Required. http/https only. |
width / height | 1280 / 800 | width 320–2000, height 200–4000. |
full_page | true | Capture the whole page. |
format | png | png / jpeg / webp. jpeg & webp take quality 10–100. |
device_scale_factor | 1 | 1–2 (retina). |
selector | — | CSS selector: capture only that element. |
delay | 1s | Extra wait after load, 0–5s. |
block_ads | true | Block ad/tracker requests. |
dark_mode | false | Prefer dark color scheme. |
Responses carry X-Render-Ms, X-Cache: HIT/MISS and X-RateLimit-Remaining. Errors are JSON: 400 bad parameter · 401 bad key · 402 daily limit reached · 422 unsafe URL · 429 rate limited (with Retry-After) · 504 render timeout · 502 target unreachable (upstream status included).
Limits: free key 20 renders/day + 5 requests/minute; 50 renders/day per IP. Images are cached for 1 hour. We do not run JavaScript you send us, and we do not accept custom headers or cookies.
Probe period: free. Every key gets 20 renders/day, no credit card, no expiry while the probe runs. Paid packs are not on sale yet — the probe is measuring what people actually need before we set prices.
If you would pay for a larger pack, tell us below. It only registers interest — no payment, no commitment.
Register interest only — no payment is taken, and paid packs do not exist yet.
How many screenshots can I take for free?
Every free key gets 20 renders per day, plus a 50 renders per day limit per IP. No credit card is required while the probe runs.
What image formats does Shot support?
PNG, JPEG and WebP. JPEG and WebP take a quality setting from 10 to 100. You can capture the full page or a single element with a CSS selector.
Are repeat screenshots cached?
Yes. The same URL and parameters are served from a 1-hour cache, and cached renders do not consume your daily quota.
Is there a rate limit?
Yes: 5 requests per minute per key, 20 renders per day per key, and 50 renders per day per IP. Over the limit you get a 429 or 402 response with a Retry-After header.
Can Shot screenshot private or internal URLs?
No. Private IPs, localhost, cloud metadata endpoints and redirect tricks are blocked. Only public http/https URLs are rendered.
Your email is used only to send your verification code and API key, and to tell you when paid packs launch. It is never sold or shared.
Render logs (the URL you asked for, when, and whether it succeeded) are kept for quota enforcement and statistics while the probe runs. Cached screenshots expire after 1 hour. Expired unused verification codes are deleted automatically.
To delete your account, API key and render history, email contact@clioos.com from the same address and we will remove them.