Signed URLs

The response of a render is the file itself, so a Shotlane URL can go straight into an <img src>: link previews, social cards, directories, dashboards. A signature makes that safe without exposing your key.

How it works

A signed URL carries your public key (pub_…, on your dashboard and in GET /v1/account) and an HMAC signature of the parameters made with your secret key. Nobody can change a parameter or reuse the URL for another page, and your secret key never leaves your server.

https://shotlane.dev/v1/screenshot?format=webp&url=https%3A%2F%2Fexample.com&key=pub_…&signature=9f2c…

Signed requests are cached for 24 hours by default (override with cache_ttl), and cache hits are free: a popular page costs one credit a day however many people view it.

Make a signature

  1. Take every parameter except key and signature, sort them by name, and URL-encode them as a query string.
  2. Put the endpoint path and ? in front, e.g. /v1/screenshot?format=webp&url=….
  3. Compute HMAC-SHA256 of that string with your secret key, as hex.
  4. Append &key=pub_…&signature=<hex>.
# Python (or: from shotlane import sign_url)
import hmac, hashlib
from urllib.parse import urlencode

def shotlane_url(params, public_key, secret_key, path="/v1/screenshot"):
    qs = urlencode(sorted((k, str(v)) for k, v in params.items()))
    sig = hmac.new(secret_key.encode(), f"{path}?{qs}".encode(), hashlib.sha256).hexdigest()
    return f"https://shotlane.dev{path}?{qs}&key={public_key}&signature={sig}"
// Node (or: import { signUrl } from "./shotlane.mjs")
import crypto from "node:crypto";

function shotlaneUrl(params, publicKey, secretKey, path = "/v1/screenshot") {
  const qs = new URLSearchParams(Object.entries(params).map(([k, v]) => [k, String(v)])
    .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))).toString();
  const sig = crypto.createHmac("sha256", secretKey).update(`${path}?${qs}`).digest("hex");
  return `https://shotlane.dev${path}?${qs}&key=${publicKey}&signature=${sig}`;
}

Python's urlencode and URLSearchParams both encode spaces as +, so they produce identical signatures.

What a signature allows

A signature is valid only for GET requests to the endpoint it was made for: /v1/screenshot, /v1/pdf, /v1/markdown or /v1/extract. It never authenticates account, job or monitor endpoints. A wrong signature or public key returns 403.

Social cards from your own template: sign a URL with html, or point url at a page you host, and set width=1200&height=630. See the guide dynamic OG images from HTML.