CDN Setup
SnapSharp emits CDN-friendly cache headers on screenshot endpoints. When a response is served from the Redis cache, you can let Cloudflare, BunnyCDN, Fastly, or any standards-compliant CDN cache it at the edge — eliminating origin egress and dropping p99 latency for popular URLs to the time it takes to hit your nearest PoP.
How it works
On every /v1/screenshot response we set:
| Header | When | Value |
|---|---|---|
Cache-Control | Cache HIT (Redis) | public, s-maxage=<ttl>, stale-while-revalidate=86400 |
Cache-Control | Cache MISS | private, no-cache |
Cache-Control | 4xx / 5xx errors | no-store (set by errorHandler) |
Vary | Cache HIT | Accept |
X-Cache | Always | HIT or MISS |
X-Edge | Always | origin (or cf-<colo> / bunny-<region> if SnapSharp serves through a CDN) |
s-maxage matches the cache_ttl query parameter you sent (default 3600,
max 86400). stale-while-revalidate=86400 lets edges keep serving the
cached byte stream for up to 24h after expiry while asynchronously
refreshing in the background.
We deliberately mark MISS responses private, no-cache. A cache miss
is the byte stream of the screenshot we just rendered for your request —
it may include cookies, JS injection, custom CSS, dark mode, etc. We let
the next identical request find it in Redis on the next request and tag
that response as cacheable.
Errors (auth failures, plan gates, SSRF, timeouts) are never cached.
Recommended TTLs per endpoint
| Endpoint | Recommended s-maxage | Notes |
|---|---|---|
/v1/screenshot | 3600 (1h) | Matches default Redis TTL. Bump higher for static marketing sites. |
/v1/og-image | 3600 (1h) | OG cards rarely change. 86400 is fine for production. |
/v1/extract | 300 (5m) | Page metadata can change frequently after deploys. |
/v1/diff | 0 (do not cache) | Diff results are pair-specific and short-lived. |
/v1/site-audit | 0 (do not cache) | Audit results are user-specific and reported once. |
Cloudflare
Put cdn.snapsharp.dev (or your own domain) in front of api.snapsharp.dev
and add a single Cache Rule:
- Match:
Hostname equals cdn.example.com AND URI Path starts with /v1/screenshot - Action:
Cache eligibility: Eligible for cache - Cache key:
Include all query string parameters(do not stripcache_ttletc — they affect the rendered output) - Edge TTL:
Respect origin Cache-Control(recommended) or set a hard cap - Browser TTL:
Respect originso users see the sameCache-Control
Optional: enable Tiered Cache so the request hops through your regional cache before reaching SnapSharp's origin. With tiered cache + SWR, popular URLs see one origin hit per hour globally.
The repo includes a starter declarative config in
infra-cf-cache-rules.json
that you can adapt for the Cloudflare Rules API or Terraform.
BunnyCDN
Create a Pull Zone backed by https://api.snapsharp.dev:
- Origin URL:
https://api.snapsharp.dev - Cache settings → Use Cache-Control headers:
On(this is the important toggle — it makes Bunny honor ours-maxage) - Cache settings → Vary cache by query string:
On - Cache settings → Cache error responses:
Off - Edge rules: optional — strip
Authorizationfrom the cache key (the Redis cache is per-URL+params, not per-API-key, so two API keys asking for the same screenshot get the same bytes).
Test with curl -I https://your-zone.b-cdn.net/v1/screenshot?url=...&token=...
and watch X-Cache: HIT flip after the first request.
Verifying it works
After fronting SnapSharp with a CDN, verify the headers from a client:
curl -sI 'https://cdn.example.com/v1/screenshot?url=https://example.com&token=YOUR_KEY' \
| grep -iE 'cache-control|x-cache|x-edge|vary'You should see:
Cache-Control: public, s-maxage=3600, stale-while-revalidate=86400
Vary: Accept
X-Cache: HIT
X-Edge: originHit the URL twice in a row — the second response should land at your CDN
edge before reaching SnapSharp at all. Most CDNs add their own cf-cache-status
or cdn-cache header so you can tell.
Putting your own CDN in front of your SnapSharp account
You don't need an enterprise plan to use a CDN — any plan can. Just point
your CDN at https://api.snapsharp.dev and add your API key as a query
param (?token=...) or a static origin header. The cache headers we emit
work transparently for any HTTP cache that respects Cache-Control: public.
Caveats:
- If you want a per-user custom
cdn.yourdomain.commapped to SnapSharp with a SAN cert, that's an enterprise feature — contact us. - Real-time invalidation across edges (push API) is on the roadmap; today you wait out the TTL or call your CDN's purge API.
Custom domains for enterprise
Enterprise customers can run on their own domain (e.g.
screenshots.yourbrand.com) with a SnapSharp-managed cert and a private
edge IP pool. See enterprise docs (coming soon) or
contact sales.