API Reference

Preview API

A simplified screenshot endpoint designed for use directly from the browser. No template setup required — pass your client key and a URL, get back a 1200×630 PNG.

Browser-only endpoint

The Preview API uses CORS and the Origin header for authentication. It is intended for use from your website's JavaScript — not from server-side code or curl. For server-side use, use the OG Screenshot API instead.

Endpoint#

GET/api/preview/:clientKey?url=<targetUrl>

Returns a 1200×630 PNG screenshot of the target URL. Authentication is via client key (URL path) and Origin header (CORS).

Authentication#

Requests are authenticated using two values:

  1. Client key — a unique key assigned to your account, embedded directly in the URL path. Find yours in Dashboard → Previews. Format: cl_ followed by 24 hexadecimal characters (e.g., cl_a1b2c3d4e5f6a1b2c3d4e5f6).
  2. Origin header — sent automatically by browsers when making cross-origin requests. The origin must match a domain you have registered. Linkshot responds with an Access-Control-Allow-Origin header scoped to that specific origin.

Localhost bypass

Requests originating from localhost or 127.0.0.1 skip all authentication checks. This makes local development seamless — no need to register a localhost domain.

Parameters#

ParameterTypeInDescription
clientKey*
stringpathYour account's client key. Format: cl_ followed by 24 hex chars. Found in Dashboard → Previews.
url*
string (URL)queryThe fully-qualified URL of the page to screenshot. Must be on a domain you have registered (except localhost).
Origin*
stringheaderSent automatically by browsers. Must match a domain in your registered domain list.

Capture Settings#

The Preview API uses fixed capture settings optimized for OG images. These cannot be customized — use the OG Screenshot API with a template for full control.

SettingValue
viewportWidth1200px
viewportHeight630px
deviceScaleFactor2 (retina)
enableTailwindInjectionfalse
waitTimeout0ms
blockPopupstrue

CORS#

The endpoint supports CORS preflight (OPTIONS) and returns origin-specific CORS headers.

200 OKCORS headers on a successful request
Response Headers
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
Vary: Origin
Content-Type: image/png
Cache-Control: public, s-maxage=43200, stale-while-revalidate=43200
X-Cache: HIT | MISS

Caching#

Preview screenshots are cached, keyed by preview/{sha256(url)}.

  • TTL: s-maxage=43200 (12 hours).
  • Background regeneration triggers when the cached object is older than 24 hours, so stale images are refreshed automatically.

Examples#

JavaScript (fetch from browser)javascript
const clientKey = 'cl_a1b2c3d4e5f6a1b2c3d4e5f6'
const targetUrl = encodeURIComponent('https://example.com/blog/my-post')

const response = await fetch(
  `https://uselinkshot.com/api/preview/${clientKey}?url=${targetUrl}`
)

if (response.ok) {
  const blob = await response.blob()
  const imageUrl = URL.createObjectURL(blob)
  document.querySelector('#preview-img').src = imageUrl
}
HTML img taghtml
<img
  src="https://uselinkshot.com/api/preview/cl_YOUR_KEY?url=https%3A%2F%2Fexample.com"
  alt="Page preview"
  width="1200"
  height="630"
/>

URL-encode the target URL

Always percent-encode the url parameter using encodeURIComponent().

Error Responses#

All errors return JSON with an error and message field.

400 Bad RequestMissing Origin header
Response Bodyjson
{
  "error": "missing_origin",
  "message": "Origin header is required. This endpoint is intended for browser use only."
}
400 Bad RequestInvalid Origin
Response Bodyjson
{
  "error": "invalid_origin",
  "message": "The Origin header is not a valid URL"
}
400 Bad RequestMissing url parameter
Response Bodyjson
{
  "error": "missing_url",
  "message": "Please provide a url query parameter"
}
400 Bad RequestInvalid URL
Response Bodyjson
{
  "error": "invalid_url",
  "message": "The provided url is not a valid URL"
}
403 ForbiddenInvalid client key
Response Bodyjson
{
  "error": "invalid_client_key",
  "message": "The provided client key is not valid"
}
403 ForbiddenOrigin not authorized — message includes the actual hostname
Response Bodyjson
{
  "error": "origin_not_authorized",
  "message": "The origin \"example.com\" is not in your registered domain list"
}
403 ForbiddenNo active subscription
Response Bodyjson
{
  "error": "no_active_subscription",
  "message": "No active subscription found for this client key"
}
500 Internal Server ErrorNavigation timeout — message includes the target URL
Response Bodyjson
{
  "error": "navigation_timeout",
  "message": "Page failed to load within timeout: https://example.com/page"
}
500 Internal Server ErrorScreenshot failed — message includes the error detail
Response Bodyjson
{
  "error": "screenshot_failed",
  "message": "Screenshot generation failed: <error detail>"
}