Signed URLs
Every render endpoint has a GET variant authenticated by an HMAC signature instead of your API key.
That means a render can live directly in an <img src>, a Notion embed, or an email —
no backend in the request path, and your API key never leaves the server.
<!-- Embed a live screenshot straight into HTML or an email -->
<img src="https://rasterkit.com/v1/screenshot?url=https%3A%2F%2Fexample.com&viewport_width=800&key_id=YOUR_KEY_ID&signature=..." width="800" alt="Latest screenshot">
<!-- Signatures are HMAC-SHA256 over the sorted query string with your
per-key signing secret. Generate them from the dashboard or your backend. --> How signatures work
- Take every query parameter except
signature(includingkey_idand optionalexpires). - Sort pairs and form
key=value&key=value…with URL-encoding. - Compute
HMAC-SHA256(signing_secret, "/v1/screenshot?" + canonical_query), hex-encoded. - Append as
&signature=….
// Node.js
import { createHmac } from 'node:crypto'
function signedScreenshotUrl(params, keyId, signingSecret) {
const qs = new URLSearchParams({ ...params, key_id: keyId })
const sorted = [...qs.entries()].sort(([a], [b]) => a.localeCompare(b))
const canonical = sorted.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&')
const signature = createHmac('sha256', signingSecret)
.update(`/v1/screenshot?${canonical}`)
.digest('hex')
return `https://rasterkit.com/v1/screenshot?${canonical}&signature=${signature}`
} Notes
- Your per-key signing secret is in the dashboard (separate from the API key).
- Add
expires(unix seconds) for time-limited links; omit it for permanent embeds. - Combine with
cache_ttlso the same embed doesn't re-render on every page view — cached hits are free. - Tampering with any parameter invalidates the signature (
401 signature_invalid).