URL → PNG · generate once, serve forever

Turn any URL into a cached thumbnail.

WebThumb captures a page once, stores the PNG at the edge, and serves it to every screen that asks. You poke a URL; your UI just points an <img> at it.

Poke to generate Served from cache 100 captures free
How it works

Two endpoints. One does the work, one serves the bytes.

Generating and serving are separated on purpose. Only your backend can ask for a capture — the public side just hands back a cached PNG, so there's nothing to abuse and everything to cache.

01POKE

You poke a URL

On save, your backend asks WebThumb for a thumbnail of a URL at a size. Fire-and-forget.

02

It captures once

A headless browser renders the page, screenshots it, and downscales to a crisp thumbnail.

03

Stored by key

The PNG lands in object storage keyed by hash(url·size·version) — deduped, immutable.

04SERVE

Served from the edge

Your <img> hits the CDN. Cold URLs fall out of the edge on their own.

POST/thumbs— generate (your backend only)
# ask for a thumbnail — idempotent
POST /thumbs
{
  "url":        "https://your-site.com/menu",
  "size":       "960x540",
  "lastupdate": 1719800000
}
→ 202  { serveUrl: "/t/9f3a…png" }
GET/t/{key}.png— serve (public, in your UI)
<!-- dumb, static, CDN-cached -->
<img src="https://webthumb.wisw.net
      /t/9f3a4c….png">

# ready  → Cache-Control: immutable, 1y
# not yet → placeholder, no-store
Capabilities

Built to be boring in production.

The interesting decisions are already made, so the thing just runs and the bill stays small.

Capture once

A URL is screenshotted a single time and frozen. No render loop, no surprise recompute, predictable cost.

no scheduler needed

Served from the edge

Immutable PNGs sit behind a CDN. Cold thumbnails LRU-evict from the edge for free — you never purge a cache.

Cache-Control: immutable

Refresh on your terms

Bump lastupdate and the key changes — a fresh capture, the old one simply goes unreferenced.

versioned keys

SSRF-safe by default

Private and link-local addresses are refused before the browser opens. Generation is gated by your app's auth.

no open proxy

Retina-crisp

Capture at a real viewport, downscale with a 2× device pixel ratio. Sharp thumbnails on every screen.

deviceScaleFactor: 2

A plain REST API

One POST to generate, one <img> to serve. No SDK, no build step — a key and a URL is the whole integration.

poke & serve
Built for

One service, every surface.

Website, app, and signage builder all read the same serveUrl. Add a URL once, it shows up everywhere.

SURFACE / 01

Website builder

Link cards and page previews that render instantly — a real screenshot instead of a favicon and a guess.

SURFACE / 02

App

Thumbnail grids that stay fast because every tile is a static, edge-cached PNG, not a live capture.

SURFACE / 03

Digital signage

Preview exactly what a screen will show. Poke when the layout is saved; the frame is ready before it goes live.

Live demo

Poke it. Watch it serve.

This is the whole interaction: a poke kicks off a capture, the tile shows a placeholder, then swaps in the served thumbnail.

🔒https://your-site.com/menu
idle — no thumbnail yet
🖼️ placeholder
Today's Menu — Bar Vetro
960×540 · 48 KB · immutable
Get started

Get an API key. 100 captures free.

Create an account, get a key, and point an <img> at your first thumbnail in minutes. No card required.