Code Examples
Copy-paste examples in cURL, JavaScript, Python, and Go.
Basic Screenshot
Capture a simple PNG screenshot of any URL:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://github.com",
"format": "png"
}'
const response = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://github.com",
format: "png",
}),
});
const data = await response.json();
console.log(data.url); // CDN URL to your screenshot
import requests
response = requests.post(
"https://api.getsnap.dev/v1/screenshot",
headers={
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
json={
"url": "https://github.com",
"format": "png",
},
)
data = response.json()
print(data["url"]) # CDN URL to your screenshot
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]interface{}{
"url": "https://github.com",
"format": "png",
})
req, _ := http.NewRequest("POST",
"https://api.getsnap.dev/v1/screenshot",
bytes.NewBuffer(body))
req.Header.Set("X-API-Key", "sk_live_YOUR_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result["url"])
}
Full Page Capture
Capture the entire scrollable page, not just the viewport:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://stripe.com/docs",
"format": "png",
"full_page": true,
"remove_popups": true
}'
const data = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://stripe.com/docs",
format: "png",
full_page: true,
remove_popups: true,
}),
}).then(r => r.json());
console.log(data.url);
response = requests.post(
"https://api.getsnap.dev/v1/screenshot",
headers={"X-API-Key": "sk_live_YOUR_KEY", "Content-Type": "application/json"},
json={
"url": "https://stripe.com/docs",
"format": "png",
"full_page": True,
"remove_popups": True,
},
)
print(response.json()["url"])
PDF Generation
Generate a PDF of any webpage — perfect for invoices, reports, or archival:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://invoice.example.com/inv-001",
"format": "pdf",
"full_page": true
}'
const { url } = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://invoice.example.com/inv-001",
format: "pdf",
full_page: true,
}),
}).then(r => r.json());
// url contains the CDN link to the generated PDF
Mobile Device Emulation
Capture as seen on a mobile or tablet device:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://tailwindcss.com",
"format": "webp",
"device": "mobile",
"quality": 90
}'
const data = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://tailwindcss.com",
format: "webp",
device: "mobile",
quality: 90,
}),
}).then(r => r.json());
Element Capture (CSS Selector)
Capture a specific element on the page using a CSS selector:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://getsnap.dev",
"format": "png",
"selector": "#pricing .price-card.featured"
}'
const data = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://getsnap.dev",
format: "png",
selector: "#pricing .price-card.featured",
}),
}).then(r => r.json());
Custom CSS Injection
Inject custom CSS before capture — hide elements, change styles, or highlight sections:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://news.ycombinator.com",
"format": "png",
"css": "header { display: none; } body { padding-top: 0; }",
"full_page": false
}'
Dark Mode
Trigger dark mode on sites that support prefers-color-scheme:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://github.com",
"format": "png",
"dark_mode": true
}'
Binary Response (Direct Download)
Get the raw image bytes instead of a CDN URL. Useful for processing or immediate display:
# Save directly to a file
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "png",
"response_type": "binary"
}' \
--output screenshot.png
import { writeFile } from "fs/promises";
const response = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://example.com",
format: "png",
response_type: "binary",
}),
});
const buffer = Buffer.from(await response.arrayBuffer());
await writeFile("screenshot.png", buffer);
console.log("Saved screenshot.png");
response = requests.post(
"https://api.getsnap.dev/v1/screenshot",
headers={"X-API-Key": "sk_live_YOUR_KEY", "Content-Type": "application/json"},
json={
"url": "https://example.com",
"format": "png",
"response_type": "binary",
},
)
with open("screenshot.png", "wb") as f:
f.write(response.content)
print("Saved screenshot.png")
Lazy Load (Auto-scroll)
Auto-scroll the page to trigger lazy-loaded images and content before capture:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://unsplash.com/t/nature",
"format": "png",
"full_page": true,
"lazy_load": true
}'
const data = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://unsplash.com/t/nature",
format: "png",
full_page: true,
lazy_load: true, // scrolls page in 300px increments to load all images
}),
}).then(r => r.json());
Wait for Selector (SPAs)
Wait for a specific element to appear before capturing. Essential for single-page apps and dynamically loaded content:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.example.com/dashboard",
"format": "png",
"wait_for_selector": ".dashboard-loaded",
"delay": 500
}'
const data = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://app.example.com/dashboard",
format: "png",
wait_for_selector: ".dashboard-loaded", // waits up to 15s
delay: 500, // extra delay after element appears
}),
}).then(r => r.json());
Hide & Remove Elements
Hide elements with CSS (display:none) or completely remove them from the DOM before capture:
# Hide elements (still in DOM, just invisible)
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "png",
"hide_selectors": ["header", ".sidebar", "#banner"],
"remove_selectors": [".cookie-notice", ".chat-widget"]
}'
const data = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://example.com",
format: "png",
hide_selectors: ["header", ".sidebar", "#banner"], // display:none
remove_selectors: [".cookie-notice", ".chat-widget"], // removed from DOM
}),
}).then(r => r.json());
Extract Text & HTML
Get the page's visible text or full HTML alongside the screenshot — perfect for scraping and content analysis:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://news.ycombinator.com",
"format": "png",
"extract_text": true,
"extract_html": true
}'
# Response includes:
# {
# "url": "https://cdn..../screenshot.png",
# "extracted_text": "Hacker News\n1. Article title...",
# "extracted_html": "<html>...</html>"
# }
const data = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://news.ycombinator.com",
format: "png",
extract_text: true,
}),
}).then(r => r.json());
console.log(data.url); // Screenshot CDN URL
console.log(data.extracted_text); // Page text content
response = requests.post(
"https://api.getsnap.dev/v1/screenshot",
headers={"X-API-Key": "sk_live_YOUR_KEY", "Content-Type": "application/json"},
json={
"url": "https://news.ycombinator.com",
"format": "png",
"extract_text": True,
"extract_html": True,
},
)
data = response.json()
print(data["extracted_text"]) # Visible text content
print(len(data["extracted_html"])) # Full HTML length
Click & Scroll to Element
Click an element (e.g., expand a menu or dismiss a dialog) or scroll to a section before capture:
# Click "Show More" button, then scroll to pricing section
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "png",
"click_selector": ".show-more-btn",
"scroll_to_selector": "#pricing",
"delay": 1000
}'
const data = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://example.com",
format: "png",
click_selector: ".show-more-btn", // clicks element (5s timeout)
scroll_to_selector: "#pricing", // scrolls into view
delay: 1000, // wait for animations
}),
}).then(r => r.json());
Render Links (Signed URLs)
Generate a signed URL that serves screenshots via GET — embed in <img> tags, OG meta, or emails without exposing your API key:
# Step 1: Generate a render link
curl -X POST https://api.getsnap.dev/v1/render-link \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://github.com/trending",
"format": "png",
"viewport_width": 1200,
"viewport_height": 630
}'
# Response:
# {
# "render_url": "https://api.getsnap.dev/v1/render?url=...&signature=...",
# "message": "Use this URL in <img> tags..."
# }
# Step 2: Use it anywhere!
# <img src="https://api.getsnap.dev/v1/render?url=...&signature=..." />
# <meta property="og:image" content="https://api.getsnap.dev/v1/render?..." />
// Generate a render link
const { render_url } = await fetch("https://api.getsnap.dev/v1/render-link", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://github.com/trending",
format: "png",
viewport_width: 1200,
viewport_height: 630,
}),
}).then(r => r.json());
// Use in HTML — no API key exposed!
const html = `<img src="${render_url}" alt="Screenshot" />`;
// Or as OG image
const meta = `<meta property="og:image" content="${render_url}" />`;
Batch Capture (Multiple URLs)
Capture up to 100 URLs in a single request — processed in parallel for maximum speed:
curl -X POST https://api.getsnap.dev/v1/batch \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://github.com",
"https://stripe.com",
"https://vercel.com",
"https://linear.app"
],
"format": "png",
"full_page": false,
"remove_popups": true
}'
# Response:
# {
# "batch_id": "batch_abc123",
# "count": 4,
# "succeeded": 4,
# "failed": 0,
# "results": [
# { "source_url": "https://github.com", "url": "https://cdn.../1.png" },
# ...
# ]
# }
const data = await fetch("https://api.getsnap.dev/v1/batch", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
urls: [
"https://github.com",
"https://stripe.com",
"https://vercel.com",
"https://linear.app",
],
format: "png",
remove_popups: true,
}),
}).then(r => r.json());
console.log(`Captured ${data.succeeded}/${data.count} screenshots`);
data.results.forEach(r => console.log(r.source_url, "->", r.url));
response = requests.post(
"https://api.getsnap.dev/v1/batch",
headers={"X-API-Key": "sk_live_YOUR_KEY", "Content-Type": "application/json"},
json={
"urls": [
"https://github.com",
"https://stripe.com",
"https://vercel.com",
"https://linear.app",
],
"format": "png",
"remove_popups": True,
},
)
data = response.json()
for result in data["results"]:
print(f"{result['source_url']} -> {result['url']}")
Transparent Background
Capture PNG screenshots with a transparent background — great for embedding in designs or compositing:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<div style=\"padding:40px;font-size:48px;font-weight:bold\">Hello World</div>",
"format": "png",
"omit_background": true
}'
Authenticated Pages (Cookies & Headers)
Capture pages behind authentication by passing cookies or custom headers:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.example.com/dashboard",
"format": "png",
"cookies": [
{ "name": "session_id", "value": "abc123", "domain": "app.example.com" }
],
"headers": {
"Authorization": "Bearer eyJhbGciOi..."
},
"wait_for_selector": ".dashboard-content"
}'
const data = await fetch("https://api.getsnap.dev/v1/screenshot", {
method: "POST",
headers: {
"X-API-Key": "sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://app.example.com/dashboard",
format: "png",
cookies: [
{ name: "session_id", value: "abc123", domain: "app.example.com" },
],
headers: {
Authorization: "Bearer eyJhbGciOi...",
},
wait_for_selector: ".dashboard-content",
}),
}).then(r => r.json());
Extract Page Metadata
Return page metadata (title, favicon, Open Graph tags, actually-loaded fonts, HTTP status, response headers) alongside the screenshot:
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://stripe.com",
"format": "png",
"extract_metadata": true
}'
import GetSnap from "getsnap";
const snap = new GetSnap("YOUR_KEY");
const r = await snap.screenshot({
url: "https://stripe.com",
extract_metadata: true,
});
console.log(r.extracted_metadata?.title);
console.log(r.extracted_metadata?.favicon);
console.log(r.extracted_metadata?.open_graph); // { "og:title": "...", ... }
console.log(r.extracted_metadata?.fonts); // ["Inter", "SF Pro Text", ...]
console.log(r.extracted_metadata?.http_status); // 200
from getsnap import GetSnap
snap = GetSnap("YOUR_KEY")
r = snap.screenshot(
url="https://stripe.com",
format="png",
extract_metadata=True,
)
meta = r["extracted_metadata"]
print(meta["title"], meta["favicon"], meta["http_status"])
print("OG tags:", meta["open_graph"])
print("Fonts:", meta["fonts"])
Clip Region
Capture a specific rectangle of the viewport instead of the full page or an element. Overrides full_page and selector.
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://openai.com",
"clip": { "x": 0, "y": 0, "width": 1280, "height": 400 }
}'
const r = await snap.screenshot({
url: "https://openai.com",
clip: { x: 0, y: 0, width: 1280, height: 400 },
});
Full-Page Slices (for AI vision)
Split a tall full_page capture into overlapping vertical strips so downstream vision models (which typically cap at ~8000px height) can process the whole page. Each slice is uploaded as its own object.
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://en.wikipedia.org/wiki/Screenshot",
"full_page": true,
"full_page_max_height": 20000,
"full_page_slices": true,
"full_page_slice_height": 4000,
"full_page_slice_overlap_height": 100
}'
const r = await snap.screenshot({
url: "https://en.wikipedia.org/wiki/Screenshot",
full_page: true,
full_page_max_height: 20000,
full_page_slices: true,
full_page_slice_height: 4000,
full_page_slice_overlap_height: 100,
});
// r.slices = [{ index, offset_y, width, height, url }, ...]
for (const s of r.slices ?? []) {
console.log(`slice ${s.index} @ y=${s.offset_y}: ${s.url}`);
}
Custom PDF (headers, footers, document metadata)
Render an invoice-style PDF with A4 landscape orientation, per-side margins, a page-number footer, and document metadata that shows up in PDF viewers.
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/invoice/INV-2026-0042",
"format": "pdf",
"pdf_page_size": "A4",
"pdf_orientation": "landscape",
"pdf_margin_top": "40px",
"pdf_margin_bottom": "40px",
"pdf_scale": 0.9,
"pdf_background": true,
"pdf_show_footer": true,
"pdf_footer": "<div style=\"font-size:10px;width:100%;text-align:center;color:#666\">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></div>",
"pdf_title": "Invoice INV-2026-0042",
"pdf_subject": "Monthly invoice",
"pdf_author": "Acme Inc.",
"pdf_keywords": "invoice,billing,acme",
"pdf_creator": "getSnap.dev"
}'
const r = await snap.screenshot({
url: "https://example.com/invoice/INV-2026-0042",
format: "pdf",
pdf_page_size: "A4",
pdf_orientation: "landscape",
pdf_margin_top: "40px",
pdf_margin_bottom: "40px",
pdf_scale: 0.9,
pdf_show_footer: true,
pdf_footer: '<div style="font-size:10px;width:100%;text-align:center;color:#666">Page <span class="pageNumber"></span> of <span class="totalPages"></span></div>',
pdf_title: "Invoice INV-2026-0042",
pdf_author: "Acme Inc.",
pdf_keywords: "invoice,billing,acme",
});
Scrolling Video (MP4/GIF)
Record a smoothly-scrolling capture of any URL. Costs 1 credit per second of video (rounded up, min 1).
# Sync mode - blocks until video is encoded
curl -X POST https://api.getsnap.dev/v1/video \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://stripe.com",
"format": "mp4",
"duration_ms": 8000,
"fps": 20,
"viewport_width": 1280,
"viewport_height": 720,
"quality": 75
}'
# Async mode - returns 202 + delivers video.completed to your webhook
curl -X POST https://api.getsnap.dev/v1/video \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://stripe.com",
"format": "gif",
"duration_ms": 4000,
"fps": 15,
"webhook_url": "https://my-app.com/webhooks/getsnap"
}'
import GetSnap from "getsnap";
const snap = new GetSnap("YOUR_KEY");
// URL mode
const mp4 = await snap.video({
url: "https://stripe.com",
format: "mp4",
duration_ms: 8000,
fps: 20,
});
console.log(mp4.url, mp4.frame_count, mp4.credits_charged);
// Binary mode - get raw MP4/GIF bytes
const buf = await snap.videoBinary({
url: "https://stripe.com",
format: "gif",
duration_ms: 5000,
});
require("fs").writeFileSync("stripe.gif", Buffer.from(buf));
from getsnap import GetSnap
snap = GetSnap("YOUR_KEY")
# URL mode
r = snap.video(
url="https://stripe.com",
format="mp4",
duration_ms=8000,
fps=20,
)
print(r["url"], r["frame_count"], r["credits_charged"])
# Binary mode
with open("stripe.gif", "wb") as f:
f.write(snap.video_binary(
url="https://stripe.com",
format="gif",
duration_ms=5000,
))
Scheduled Captures
Cron-driven recurring captures with optional HMAC-signed webhook delivery. Great for daily dashboards, hourly competitor snapshots, or weekly compliance archives.
# Create - runs every weekday at 09:00 Berlin time
curl -X POST https://api.getsnap.dev/v1/schedules \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "morning traffic dashboard",
"cron": "0 9 * * MON-FRI",
"timezone": "Europe/Berlin",
"options": {
"url": "https://dash.example.com",
"format": "png",
"full_page": true,
"viewport_width": 1600
},
"webhook_url": "https://my-app.com/webhooks/getsnap",
"webhook_secret": "a-strong-shared-secret-abcd1234"
}'
# Trigger immediately (for testing)
curl -X POST https://api.getsnap.dev/v1/schedules/sched_ABC123/run \
-H "x-api-key: YOUR_KEY"
# List runs
curl https://api.getsnap.dev/v1/schedules/sched_ABC123/runs \
-H "x-api-key: YOUR_KEY"
# Pause
curl -X PATCH https://api.getsnap.dev/v1/schedules/sched_ABC123 \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"is_active": false}'
import GetSnap from "getsnap";
const snap = new GetSnap("YOUR_KEY");
// Create
const s = await snap.schedules.create({
name: "morning traffic dashboard",
cron: "0 9 * * MON-FRI",
timezone: "Europe/Berlin",
options: {
url: "https://dash.example.com",
full_page: true,
viewport_width: 1600,
},
webhook_url: "https://my-app.com/webhooks/getsnap",
webhook_secret: process.env.WEBHOOK_SECRET,
});
// Trigger it now (returns immediately, worker runs in background)
await snap.schedules.runNow(s.id);
// Poll history
const { runs } = await snap.schedules.runs(s.id);
console.log(runs[0]?.status, runs[0]?.result_url);
// Pause / resume / delete
await snap.schedules.update(s.id, { is_active: false });
await snap.schedules.update(s.id, { is_active: true });
await snap.schedules.remove(s.id);
from getsnap import GetSnap
snap = GetSnap("YOUR_KEY")
s = snap.create_schedule(
name="morning traffic dashboard",
cron="0 9 * * MON-FRI",
timezone="Europe/Berlin",
options={
"url": "https://dash.example.com",
"full_page": True,
"viewport_width": 1600,
},
webhook_url="https://my-app.com/webhooks/getsnap",
webhook_secret="a-strong-shared-secret-abcd1234",
)
# Trigger it now
snap.run_schedule_now(s["id"])
# Poll history
for run in snap.list_schedule_runs(s["id"])["runs"]:
print(run["status"], run.get("result_url"), run.get("error"))
# Update / delete
snap.update_schedule(s["id"], is_active=False)
snap.delete_schedule(s["id"])
Verify HMAC-signed webhooks
When you set webhook_secret, every delivery includes X-Webhook-Timestamp (seconds since epoch) and X-Webhook-Signature: sha256=<hex> where the HMAC is computed over timestamp + "." + raw_body. Verify server-side:
// Node.js webhook receiver
import crypto from "node:crypto";
app.post("/webhooks/getsnap", express.raw({ type: "application/json" }), (req, res) => {
const ts = req.header("X-Webhook-Timestamp") ?? "";
const sig = req.header("X-Webhook-Signature") ?? "";
const body = req.body.toString("utf8");
const expected = "sha256=" + crypto
.createHmac("sha256", process.env.WEBHOOK_SECRET)
.update(ts + "." + body)
.digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!ok) return res.sendStatus(401);
// Also reject deliveries older than 5 minutes to defeat replay
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(401);
const event = JSON.parse(body);
console.log(event.event, event.schedule_id, event.url);
res.sendStatus(200);
});
Proxy / Geo Routing
Route any capture through your own proxy (BYOP) or a managed geo pool. Works on both /v1/screenshot and /v1/video.
# BYOP - creds embedded in the URL
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"proxy_url": "http://user:pass@proxy.mycompany.com:8080"
}'
# BYOP - creds split (safer to log)
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"proxy_url": "socks5://proxy.mycompany.com:1080",
"proxy_username": "alice",
"proxy_password": "secret"
}'
# Managed geo pool - capture from a US IP
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://us-only.example.com",
"proxy_country": "US"
}'
// BYOP
await snap.screenshot({
url: "https://example.com",
proxy_url: "http://proxy.mycompany.com:8080",
proxy_username: "alice",
proxy_password: process.env.PROXY_PASSWORD,
});
// Managed geo pool
await snap.screenshot({
url: "https://us-only.example.com",
proxy_country: "US",
});
// Works on video too
await snap.video({
url: "https://us-only.example.com",
format: "mp4",
duration_ms: 5000,
proxy_country: "US",
});
# BYOP
snap.screenshot(
url="https://example.com",
proxy_url="http://proxy.mycompany.com:8080",
proxy_username="alice",
proxy_password=os.environ["PROXY_PASSWORD"],
)
# Managed geo pool
snap.screenshot(
url="https://us-only.example.com",
proxy_country="US",
)
# Works on video too
snap.video(
url="https://us-only.example.com",
format="mp4",
duration_ms=5000,
proxy_country="US",
)
Granular Request Blocking
Cut page load time (and bandwidth) by aborting requests you don't need. Combine with bypass_csp when a site's Content-Security-Policy blocks your injected CSS/JS.
curl -X POST https://api.getsnap.dev/v1/screenshot \
-H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://news-heavy-site.com/article/123",
"block_images": true,
"block_fonts": true,
"block_scripts": true,
"block_frames": true,
"block_urls": ["*/analytics/*", "*/beacon/*", "chartbeat"],
"click_accept": true,
"press_escape": true
}'
await snap.screenshot({
url: "https://news-heavy-site.com/article/123",
block_images: true,
block_fonts: true,
block_scripts: true,
block_frames: true,
block_urls: ["*/analytics/*", "*/beacon/*", "chartbeat"],
click_accept: true,
press_escape: true,
});
Node.js SDK
Use the official SDK for a cleaner developer experience with full TypeScript support:
import GetSnap from "getsnap";
const snap = new GetSnap("sk_live_YOUR_KEY");
// Simple screenshot
const { url } = await snap.screenshot({
url: "https://github.com",
format: "png",
full_page: true,
});
console.log(url);
// Binary download
const buffer = await snap.screenshotBinary({
url: "https://example.com",
format: "webp",
quality: 90,
});
await writeFile("screenshot.webp", Buffer.from(buffer));
// Batch capture
const batch = await snap.batch({
urls: ["https://github.com", "https://stripe.com"],
format: "png",
});
console.log(`${batch.succeeded} screenshots captured`);
// Check usage
const usage = await snap.usage();
console.log(`${usage.used}/${usage.limit} screenshots used`);
Python SDK
Zero-dependency Python SDK using only the standard library:
from getsnap import GetSnap
snap = GetSnap("sk_live_YOUR_KEY")
# Simple screenshot
result = snap.screenshot(url="https://github.com", format="png")
print(result["url"])
# Binary download
binary = snap.screenshot_binary(url="https://example.com", format="webp")
with open("screenshot.webp", "wb") as f:
f.write(binary)
# Batch capture
batch = snap.batch(
urls=["https://github.com", "https://stripe.com"],
format="png",
remove_popups=True,
)
for r in batch["results"]:
print(f"{r['source_url']} -> {r['url']}")
# Check usage
usage = snap.usage()
print(f"{usage['used']}/{usage['limit']} screenshots used")