API examples

Production-ready recipes, as URLs, cURL, and SDK calls.

Copy-paste recipes for screenshots, PDFs, content extraction, batch jobs, visual diffs, and async webhooks. Flip the switch to see a direct URL, raw HTTP request, or typed SDK call for the same result.

Base URL https://api.snapshotflow.com · authenticate with your API key from the dashboard.

0

Set up once

Shell

# Grab your key from the dashboard (Account → API Keys)
export API_KEY="e2e_your_key_here"

# Every request authenticates with the X-Api-Key header.
# (You can also pass ?api_key=... in the query string.)
curl "https://api.snapshotflow.com/screenshot?url=https://example.com" \
      -H "X-Api-Key: $API_KEY" -o page.png

Direct URL

https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&format=png&url=https://apple.com

Install

npm install snapshotflow   # requires Node.js >= 18

Create the client (reused by every example below)

import { SnapshotFlow, TakeOptions } from "snapshotflow";

const client = new SnapshotFlow({
  apiKey: process.env.SNAPSHOTFLOW_API_KEY,
  baseUrl: "https://api.snapshotflow.com",
  // timeoutMs and maxRetries are optional
});

Capture basics

The everyday screenshot calls.

Basic screenshot (PNG)

The simplest request — one URL in, a binary PNG out.

url
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com" \
  -H "X-Api-Key: $API_KEY" -o stripe.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com
const shot = await client.take({ url: "https://stripe.com" });
await shot.save("stripe.png");
console.log("cached:", shot.cached, "type:", shot.contentType);

Full-page JPEG with quality

Capture the whole scrollable page as a compressed JPEG.

full_pageformatquality
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&full_page=true&format=jpeg&quality=85" \
  -H "X-Api-Key: $API_KEY" -o full.jpg
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&full_page=true&format=jpeg&quality=85
const shot = await client.take(
  TakeOptions.url("https://stripe.com")
    .fullPage(true)
    .format("jpeg")
    .quality(85),
);
await shot.save("full.jpg");

Retina & custom viewport

A 1440×900 viewport at 2× device scale for crisp, high-DPI output.

widthheightdevice_scale_factor
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&width=1440&height=900&device_scale_factor=2" \
  -H "X-Api-Key: $API_KEY" -o retina.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&width=1440&height=900&device_scale_factor=2
const shot = await client.take({
  url: "https://stripe.com",
  width: 1440,
  height: 900,
  deviceScaleFactor: 2,
});
await shot.save("retina.png");

One element only (selector)

Crop the capture to a single CSS selector — great for cards or tables.

selectoromit_background
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&selector=.PricingTable&omit_background=true" \
  -H "X-Api-Key: $API_KEY" -o pricing.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&selector=main&omit_background=true
const shot = await client.take({
  url: "https://stripe.com",
  selector: ".PricingTable",
  omitBackground: true,   // transparent PNG
});
await shot.save("pricing.png");

Mobile viewport + dark mode

Emulate a mobile device and force the dark color scheme.

viewport_mobiledark_mode
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&viewport_mobile=true&dark_mode=true" \
  -H "X-Api-Key: $API_KEY" -o mobile-dark.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&viewport_mobile=true&dark_mode=true
const shot = await client.take({
  url: "https://stripe.com",
  viewportMobile: true,
  darkMode: true,
});
await shot.save("mobile-dark.png");

Render raw HTML

Screenshot an HTML string instead of a URL — pass it base64-encoded.

html
HTML=$(printf '<h1>Hello</h1>' | base64)
curl "https://api.snapshotflow.com/screenshot?html=$HTML&format=png" \
  -H "X-Api-Key: $API_KEY" -o html.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&html=PGgxPkhlbGxvPC9oMT4%3D&format=png
// The SDK base64-encodes the HTML for you.
const shot = await client.take({
  html: "<h1>Hello</h1>",
  format: "png",
});
await shot.save("html.png");

Clean & control

Block noise, wait for content, inject your own code.

Block ads, trackers & cookie banners

Strip the clutter and hide your own selectors for a clean capture.

block_adsblock_trackersblock_cookie_bannershide_selectors
curl "https://api.snapshotflow.com/screenshot?url=https://news.ycombinator.com&block_ads=true&block_trackers=true&block_cookie_banners=true&hide_selectors=.intercom-launcher" \
  -H "X-Api-Key: $API_KEY" -o clean.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&block_ads=true&block_trackers=true&block_cookie_banners=true&hide_selectors=.intercom-launcher
const shot = await client.take({
  url: "https://news.ycombinator.com",
  blockAds: true,
  blockTrackers: true,
  blockCookieBanners: true,
  hideSelectors: [".intercom-launcher"],
});
await shot.save("clean.png");

Wait for a SPA to render

Hold the capture until an element appears and the network settles.

wait_for_selectorwait_untildelay
curl "https://api.snapshotflow.com/screenshot?url=https://app.example.com&wait_for_selector=.dashboard-loaded&wait_until=networkidle0&delay=500" \
  -H "X-Api-Key: $API_KEY" -o spa.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&wait_for_selector=main&wait_until=networkidle0&delay=500
const shot = await client.take({
  url: "https://app.example.com",
  waitForSelector: ".dashboard-loaded",
  waitUntil: "networkidle0",
  delay: 500,
});
await shot.save("spa.png");

Authenticated page (headers + cookies)

Send auth headers and session cookies to capture a logged-in view.

headerscookies
curl -G "https://api.snapshotflow.com/screenshot" \
  -H "X-Api-Key: $API_KEY" \
  --data-urlencode "url=https://app.example.com/billing" \
  --data-urlencode 'headers={"Authorization":"Bearer token123"}' \
  --data-urlencode 'cookies=[{"name":"session","value":"abc","domain":"app.example.com"}]' \
  -o billing.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com/shop&headers=%7B%22Authorization%22%3A%22Bearer%20token123%22%7D&cookies=%5B%7B%22name%22%3A%22session%22%2C%22value%22%3A%22abc%22%2C%22domain%22%3A%22apple.com%22%7D%5D
const shot = await client.take({
  url: "https://app.example.com/billing",
  headers: { Authorization: "Bearer token123" },
  cookies: [
    { name: "session", value: "abc", domain: "app.example.com" },
  ],
});
await shot.save("billing.png");

Inject CSS/JS & click first

Patch the page, dismiss a modal, then capture the result.

stylesscriptsclick
curl -G "https://api.snapshotflow.com/screenshot" \
  -H "X-Api-Key: $API_KEY" \
  --data-urlencode "url=https://example.com" \
  --data-urlencode "styles=.promo-bar{display:none}" \
  --data-urlencode "scripts=document.title='Snap'" \
  --data-urlencode "click=#accept-modal .close" \
  -o patched.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&styles=.promo-bar%7Bdisplay%3Anone%7D&scripts=document.title%3D%27Snap%27&click=button
const shot = await client.take({
  url: "https://example.com",
  styles: ".promo-bar{display:none}",
  scripts: "document.title='Snap'",
  click: "#accept-modal .close",
});
await shot.save("patched.png");

Geolocation & timezone

Render the page as if the browser were in another location.

timezonegeolocation_latitudegeolocation_longitude
curl "https://api.snapshotflow.com/screenshot?url=https://example.com&timezone=Europe/Paris&geolocation_latitude=48.8566&geolocation_longitude=2.3522&geolocation_accuracy=50" \
  -H "X-Api-Key: $API_KEY" -o paris.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&timezone=Europe/Paris&geolocation_latitude=48.8566&geolocation_longitude=2.3522&geolocation_accuracy=50
// The fluent builder exposes .geolocation(lat, lng, accuracy).
const shot = await client.take(
  TakeOptions.url("https://example.com")
    .timezone("Europe/Paris")
    .geolocation(48.8566, 2.3522, 50),
);
await shot.save("paris.png");

// Plain-object equivalent uses flat keys:
// { geolocationLatitude: 48.8566, geolocationLongitude: 2.3522,
//   geolocationAccuracy: 50, timezone: "Europe/Paris" }

Generate an <img> URL

Build a ready-to-embed URL with no request — the key goes in the query string, so use only where exposing it is OK.

api_keyfull_page
<!-- Embed directly in HTML -->
<img
  src="https://api.snapshotflow.com/screenshot?url=https://stripe.com&full_page=true&api_key=e2e_your_key_here"
  alt="stripe.com">
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&full_page=true
// No network call — just builds the URL string.
const imgUrl = client.generateUrl({
  url: "https://stripe.com",
  fullPage: true,
});
// => use directly in an <img src>

Advanced rendering

Crop, resize, emulate, and fine-tune the request.

Crop a fixed region (clip)

Capture an exact rectangle by coordinates — perfect for OG cards.

clip_xclip_yclip_widthclip_height
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&clip_x=0&clip_y=0&clip_width=1200&clip_height=630" \
  -H "X-Api-Key: $API_KEY" -o og-card.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&clip_x=0&clip_y=0&clip_width=1200&clip_height=630
// Builder: .clip(x, y, width, height)
const shot = await client.take(
  TakeOptions.url("https://stripe.com").clip(0, 0, 1200, 630),
);
await shot.save("og-card.png");

// Plain-object equivalent:
// { clipX: 0, clipY: 0, clipWidth: 1200, clipHeight: 630 }

Resize the output

Render at a large viewport, then downscale the final image to exact pixels.

image_widthimage_height
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&width=1440&height=900&image_width=600&image_height=375" \
  -H "X-Api-Key: $API_KEY" -o thumb.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&width=1440&height=900&image_width=600&image_height=375
const shot = await client.take({
  url: "https://stripe.com",
  width: 1440,
  height: 900,
  imageWidth: 600,    // downscale after capture
  imageHeight: 375,
});
await shot.save("thumb.png");

Reduced motion & print media

Freeze animations and emulate @media print styles.

reduced_motionmedia_type
curl "https://api.snapshotflow.com/screenshot?url=https://example.com&reduced_motion=true&media_type=print" \
  -H "X-Api-Key: $API_KEY" -o print.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&reduced_motion=true&media_type=print
const shot = await client.take({
  url: "https://example.com",
  reducedMotion: true,
  mediaType: "print",   // "screen" | "print"
});
await shot.save("print.png");

Custom user agent

Identify your crawler or trigger UA-specific rendering.

user_agent
curl -G "https://api.snapshotflow.com/screenshot" \
  -H "X-Api-Key: $API_KEY" \
  --data-urlencode "url=https://example.com" \
  --data-urlencode "user_agent=SnapshotFlowBot/1.0 (+https://example.com/bot)" \
  -o ua.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&user_agent=SnapshotFlowBot/1.0
const shot = await client.take({
  url: "https://example.com",
  userAgent: "SnapshotFlowBot/1.0 (+https://example.com/bot)",
});
await shot.save("ua.png");

Block specific requests

Drop requests matching URL patterns — heavy scripts, beacons, third-party widgets.

block_requests
curl -G "https://api.snapshotflow.com/screenshot" \
  -H "X-Api-Key: $API_KEY" \
  --data-urlencode "url=https://example.com" \
  --data-urlencode "block_requests=*.googletagmanager.com,*/analytics.js,*.hotjar.com" \
  -o light.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&block_requests=*.googletagmanager.com,*/analytics.js,*.hotjar.com
const shot = await client.take({
  url: "https://example.com",
  blockRequests: [
    "*.googletagmanager.com",
    "*/analytics.js",
    "*.hotjar.com",
  ],
});
await shot.save("light.png");

Output formats

PDFs, JSON metadata, and LLM-ready content.

PDF export

Landscape A4 with CSS backgrounds — ideal for invoices and reports.

format=pdfpdf_print_backgroundpdf_landscapepdf_paper_format
curl "https://api.snapshotflow.com/screenshot?url=https://example.com&format=pdf&pdf_print_background=true&pdf_landscape=true&pdf_paper_format=a4" \
  -H "X-Api-Key: $API_KEY" -o report.pdf
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&format=pdf&pdf_print_background=true&pdf_landscape=true&pdf_paper_format=a4
const pdf = await client.take({
  url: "https://example.com",
  format: "pdf",
  pdfPrintBackground: true,
  pdfLandscape: true,
  pdfPaperFormat: "a4",
});
await pdf.save("report.pdf");

LLM context (image + markdown)

Return a base64 image plus the page as markdown and metadata in one call.

response_type=base64extract_contentcontent_formatmetadata
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&response_type=base64&extract_content=true&content_format=markdown&metadata=true" \
  -H "X-Api-Key: $API_KEY"
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&response_type=base64&extract_content=true&content_format=markdown&metadata=true
const res = await client.takeJson({
  url: "https://stripe.com",
  responseType: "base64",
  extractContent: true,
  contentFormat: "markdown",
  metadata: true,
});
console.log(res.metadata?.title);
console.log(res.content?.slice(0, 200));   // markdown
// res.image -> "data:image/png;base64,..."

Hosted download URL

Skip the bytes — get back a signed storage URL you can drop into an <img>.

response_type=url
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&response_type=url" \
  -H "X-Api-Key: $API_KEY"
# -> https://storage.googleapis.com/...signed...
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&response_type=url
const url = await client.takeUrl({ url: "https://stripe.com" });
// 1-hour signed URL, ready for an <img src>
console.log(url);

Force a fresh capture

Bypass the cache when you need the very latest render (cache hits are free).

cache=false
curl "https://api.snapshotflow.com/screenshot?url=https://example.com&cache=false" \
  -H "X-Api-Key: $API_KEY" -o fresh.png
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&cache=false
const shot = await client.take({
  url: "https://example.com",
  cache: false,
});
await shot.save("fresh.png");

Batch, diff & async

Multi-URL jobs, visual regression, and webhooks.

Batch capture (up to 10 URLs)

Render many pages in one parallel request; each result is independent.

POST /batchurlsresponse_type
curl -X POST "https://api.snapshotflow.com/batch" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: $API_KEY" \
  -d '{
    "urls": ["https://stripe.com", "https://vercel.com"],
    "full_page": true,
    "response_type": "base64"
  }'
POST https://api.snapshotflow.com/batch?api_key=e2e_your_key_here

{
  "urls": ["https://stripe.com", "https://vercel.com"],
  "full_page": true,
  "response_type": "base64"
}
const batch = await client.batch({
  urls: ["https://stripe.com", "https://vercel.com"],
  fullPage: true,
  responseType: "base64",
});
console.log("total:", batch.total);
for (const r of batch.results) {
  if (r.error) console.warn(r.url, r.error);
  else console.log(r.url, r.cached);
}

Visual diff (before / after)

Pixel-compare two URLs. Charges 2 quota units — one per render.

GET /diffbeforeafterthreshold
curl -G "https://api.snapshotflow.com/diff" \
  -H "X-Api-Key: $API_KEY" \
  --data-urlencode "before=https://myapp.com/v1" \
  --data-urlencode "after=https://myapp.com/v2" \
  --data-urlencode "threshold=0.1" \
  --data-urlencode "response_type=json"
# -> { "changed_pixels": 14320, "diff_percent": 1.40, "has_changes": true }
https://api.snapshotflow.com/diff?api_key=e2e_your_key_here&before=https://apple.com&after=https://apple.com/shop&threshold=0.1&response_type=json
const diff = await client.diff({
  before: "https://myapp.com/v1",
  after: "https://myapp.com/v2",
  threshold: 0.1,
  responseType: "json",
});
console.log(diff.diff_percent, diff.changed_pixels, diff.has_changes);

Correlate & report async jobs

Tag a job with your own ID (echoed back as X-SnapshotFlow-External-Id) and opt in to failure webhooks.

asyncwebhook_urlexternal_identifierwebhook_errors
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&async=true&webhook_url=https://yourapp.com/hooks&external_identifier=order-42&webhook_errors=true" \
  -H "X-Api-Key: $API_KEY"
# The webhook POST carries header: X-SnapshotFlow-External-Id: order-42
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&async=true&webhook_url=https://yourapp.com/hooks&external_identifier=order-42&webhook_errors=true
const job = await client.takeAsync({
  url: "https://stripe.com",
  webhookUrl: "https://yourapp.com/hooks",
  externalIdentifier: "order-42",   // echoed back for correlation
  webhookErrors: true,              // also POST when the job fails
});
console.log(job.jobId, job.status);

Async capture with a webhook

Queue a heavier job, get a job_id back immediately, and either poll the job or receive a webhook when it finishes.

asyncwebhook_urlGET /jobs/:id
# 1. Enqueue — returns 202 + { "job_id": "...", "status": "pending" }
curl "https://api.snapshotflow.com/screenshot?url=https://stripe.com&async=true&webhook_url=https://yourapp.com/hooks/snapshot" \
  -H "X-Api-Key: $API_KEY"

# 2. (Optional) Poll the job instead of waiting for the webhook
curl "https://api.snapshotflow.com/jobs/550e8400-..." -H "X-Api-Key: $API_KEY"
# -> { "status": "done", "result": { "storagePath": "https://..." } }
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&async=true&webhook_url=https://yourapp.com/hooks/snapshot

https://api.snapshotflow.com/jobs/550e8400-...?api_key=e2e_your_key_here
// Start the job
const { jobId, status } = await client.takeAsync({
  url: "https://stripe.com",
  webhookUrl: "https://yourapp.com/hooks/snapshot",
});
console.log(jobId, status);   // "pending"

// Either poll once...
const job = await client.getJob(jobId);

// ...or wait until it finishes (done | failed | timeout)
const done = await client.waitForJob(jobId);
console.log(done.result?.storagePath);

Verify an incoming webhook

Validate the X-SnapshotFlow-Signature header against the raw request body — never re-serialize first.

verifyWebhookX-SnapshotFlow-Signature
# The webhook is an HTTP POST your server receives.
# Verification is HMAC-SHA256 over the raw body, keyed by your
# webhook secret. Use the SDK helper (right tab) — or replicate
# the t=...,sha256=... scheme in your language of choice.
#
# Header: X-SnapshotFlow-Signature: t=1716309930,sha256=9f86d0...
POST https://yourapp.com/hooks/snapshot
X-SnapshotFlow-Signature: t=1716309930,sha256=9f86d0...

{
  "job_id": "550e8400-...",
  "status": "done",
  "external_identifier": "order-42"
}
import { SnapshotFlow } from "snapshotflow";

// In your webhook route — pass the RAW body bytes.
const ok = SnapshotFlow.verifyWebhook({
  rawBody,                                       // raw request body
  signatureHeader: req.header("x-snapshotflow-signature"),
  secret: process.env.SNAPSHOTFLOW_WEBHOOK_SECRET,
  // toleranceSec: 300,  // freshness window; 0 disables
});
if (!ok) return res.status(400).end();

Error handling

Handle quota, rate limits, and bad URLs.

Errors return a machine-readable error code; the SDK maps each one to a typed class so you can branch on it.

# Non-2xx responses carry a JSON body:
# { "error": "QUOTA_EXCEEDED", "message": "Used 300 of 300.", "quota": {...} }
curl -s -o out.png -w "%{http_code}\n" \
  "https://api.snapshotflow.com/screenshot?url=https://example.com" \
  -H "X-Api-Key: $API_KEY"
# 200 ok · 402 QUOTA_EXCEEDED · 429 RATE_LIMITED (see Retry-After) · 400 INVALID_URL
https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com

# Non-2xx responses carry JSON:
# 402 QUOTA_EXCEEDED · 429 RATE_LIMITED · 400 INVALID_URL
import { QuotaExceededError, RateLimitError, InvalidUrlError } from "snapshotflow";

try {
  const shot = await client.take({ url: "https://example.com" });
  await shot.save("out.png");
} catch (err) {
  if (err instanceof RateLimitError) {
    // back off and retry later
  } else if (err instanceof QuotaExceededError) {
    console.log(err.details?.quota);   // { used, limit, remaining }
  } else if (err instanceof InvalidUrlError) {
    console.log("bad url");
  } else {
    throw err;
  }
}

Full reference

Every /screenshot parameter in one request.

A single payload that sets every supported option. It's a reference, not a recommended combo — some keys are mutually exclusive in practice (e.g. selector vs full_page vs clip_*). Keep the ones you need and drop the rest.

cURL — every query parameter

curl -G "https://api.snapshotflow.com/screenshot" \
  -H "X-Api-Key: $API_KEY" \
  --data-urlencode "url=https://stripe.com" \
  --data-urlencode "width=1440" \
  --data-urlencode "height=900" \
  --data-urlencode "device_scale_factor=2" \
  --data-urlencode "viewport_mobile=false" \
  --data-urlencode "format=jpeg" \
  --data-urlencode "quality=90" \
  --data-urlencode "full_page=true" \
  --data-urlencode "omit_background=false" \
  --data-urlencode "selector=main" \
  --data-urlencode "clip_x=0" \
  --data-urlencode "clip_y=0" \
  --data-urlencode "clip_width=1440" \
  --data-urlencode "clip_height=900" \
  --data-urlencode "image_width=720" \
  --data-urlencode "image_height=450" \
  --data-urlencode "delay=500" \
  --data-urlencode "wait_until=networkidle0" \
  --data-urlencode "wait_for_selector=#app" \
  --data-urlencode "dark_mode=true" \
  --data-urlencode "reduced_motion=true" \
  --data-urlencode "media_type=screen" \
  --data-urlencode "timezone=Europe/Paris" \
  --data-urlencode "geolocation_latitude=48.8566" \
  --data-urlencode "geolocation_longitude=2.3522" \
  --data-urlencode "geolocation_accuracy=50" \
  --data-urlencode "user_agent=SnapshotFlowBot/1.0" \
  --data-urlencode 'headers={"Authorization":"Bearer token123"}' \
  --data-urlencode 'cookies=[{"name":"session","value":"abc","domain":"stripe.com"}]' \
  --data-urlencode "scripts=document.body.classList.add('snap')" \
  --data-urlencode "styles=.cookie-banner{display:none}" \
  --data-urlencode "hide_selectors=.intercom-launcher,.ad-slot" \
  --data-urlencode "click=#accept-cookies" \
  --data-urlencode "block_ads=true" \
  --data-urlencode "block_trackers=true" \
  --data-urlencode "block_cookie_banners=true" \
  --data-urlencode "block_requests=*.hotjar.com,*/analytics.js" \
  --data-urlencode "extract_content=true" \
  --data-urlencode "content_format=markdown" \
  --data-urlencode "metadata=true" \
  --data-urlencode "cache=true" \
  --data-urlencode "response_type=base64"

URL — every query parameter

https://api.snapshotflow.com/screenshot?api_key=e2e_your_key_here&url=https://apple.com&width=1440&height=900&device_scale_factor=2&viewport_mobile=false&format=jpeg&quality=90&full_page=true&omit_background=false&selector=main&clip_x=0&clip_y=0&clip_width=1440&clip_height=900&image_width=720&image_height=450&delay=500&wait_until=networkidle0&wait_for_selector=main&dark_mode=true&reduced_motion=true&media_type=screen&timezone=Europe/Paris&geolocation_latitude=48.8566&geolocation_longitude=2.3522&geolocation_accuracy=50&user_agent=SnapshotFlowBot/1.0&headers=%7B%22Authorization%22%3A%22Bearer%20token123%22%7D&cookies=%5B%7B%22name%22%3A%22session%22%2C%22value%22%3A%22abc%22%2C%22domain%22%3A%22apple.com%22%7D%5D&scripts=document.body.classList.add%28%27snap%27%29&styles=.cookie-banner%7Bdisplay%3Anone%7D&hide_selectors=.intercom-launcher,.ad-slot&click=button&block_ads=true&block_trackers=true&block_cookie_banners=true&block_requests=*.hotjar.com,*/analytics.js&extract_content=true&content_format=markdown&metadata=true&cache=true&response_type=base64&pdf_print_background=true&pdf_landscape=true&pdf_paper_format=a4&async=true&webhook_url=https://yourapp.com/hooks&external_identifier=order-42&webhook_errors=true

Node SDK — every option (camelCase)

const result = await client.takeJson({
  // Source
  url: "https://stripe.com",                 // or html: "<h1>Hi</h1>"
  // Viewport
  width: 1440,
  height: 900,
  deviceScaleFactor: 2,
  viewportMobile: false,
  // Capture
  format: "jpeg",                            // png | jpeg | webp | pdf
  quality: 90,
  fullPage: true,
  omitBackground: false,
  selector: "main",
  clipX: 0, clipY: 0, clipWidth: 1440, clipHeight: 900,
  imageWidth: 720, imageHeight: 450,
  // Timing
  delay: 500,
  waitUntil: "networkidle0",
  waitForSelector: "#app",
  // Emulation
  darkMode: true,
  reducedMotion: true,
  mediaType: "screen",                       // screen | print
  timezone: "Europe/Paris",
  geolocationLatitude: 48.8566,
  geolocationLongitude: 2.3522,
  geolocationAccuracy: 50,
  userAgent: "SnapshotFlowBot/1.0",
  // Injection & interaction
  headers: { Authorization: "Bearer token123" },
  cookies: [{ name: "session", value: "abc", domain: "stripe.com" }],
  scripts: "document.body.classList.add('snap')",
  styles: ".cookie-banner{display:none}",
  hideSelectors: [".intercom-launcher", ".ad-slot"],
  click: "#accept-cookies",
  // Blocking
  blockAds: true,
  blockTrackers: true,
  blockCookieBanners: true,
  blockRequests: ["*.hotjar.com", "*/analytics.js"],
  // Content & metadata
  extractContent: true,
  contentFormat: "markdown",                 // html | markdown | text
  metadata: true,
  // Cache & response
  cache: true,
  responseType: "base64",                    // image | json | base64 | url
});

console.log(result.metadata?.title, result.content?.length);

PDF-only keys (pdf_print_background, pdf_landscape, pdf_paper_format) apply when format=pdf; async keys (async, webhook_url, external_identifier, webhook_errors) are shown above as production recipes and included in the URL reference.

Try these with 300 free screenshots.

Create an account, issue an API key, and run any example above against the hosted API — no credit card required.