SnapForge API Documentation

SnapForge provides a REST API for capturing screenshots and extracting structured data from any URL. Send a GET request with your API key and a target URL to receive a PNG, JPEG, WebP, or PDF. Code examples available in cURL, Python, Node.js, and Go.

1 Quick Start

Get your first screenshot in under a minute. Sign up to get your API key - no credit card required.

cURL
curl "https://api.snapforge.techyowls.io/v1/screenshot?url=https://example.com" \
  -H "X-API-Key: YOUR_API_KEY" \
  --output screenshot.png

That's it! The API returns a PNG image by default. Cached requests return in ~50ms!

Base URL

https://api.snapforge.techyowls.io

All API endpoints are relative to this base URL.

2 Authentication

All requests require an API key sent via the X-API-Key header.

Header Format
X-API-Key: sk_live_xxxxxxxxxxxxx

Get your API key: Sign up for free - no credit card required. 50 screenshots/day included!

Take Screenshot

GET /v1/screenshot

Captures a screenshot of the specified URL. Returns image binary (default) or JSON with CDN URL.

Parameters

Core Parameters

Parameter Type Default Description
url* string - URL to capture (must be valid HTTP/HTTPS)
format string png png, jpeg, webp, or pdf
width integer 1280 Viewport width (1-3840)
height integer 720 Viewport height (1-2160)
full_page boolean false Capture entire scrollable page
delay integer 0 Wait ms before capture (0-30000)
quality integer - JPEG/WebP quality (1-100)
response_type string binary binary (image) or json (CDN URL)

Caching Parameters

Parameter Type Default Description
cache string true Use cache: true or false
max_age integer 86400 Max cache age in seconds (3600-604800)

PDF Parameters

Parameter Type Default Description
page_size string A4 A4, Letter, Legal, Tabloid
orientation string portrait portrait or landscape
margin string normal none, small, normal, large
print_background boolean true Include background colors/images

Auto-Clean Parameters (Free)

Parameter Type Default Description
clean boolean false Remove common annoyances (all below)
clean_cookies boolean false Remove cookie consent banners
clean_chat boolean false Remove chat widgets
clean_popups boolean false Remove modal popups

* Required parameter

Blocking Parameters Starter+

Parameter Type Default Description
block_ads boolean false Block advertisements
block_trackers boolean false Block tracking scripts
block_cookie_banners boolean false Block cookie consent banners via request interception
basic_auth JSON - HTTP Basic Auth: {"username":"x","password":"y"}

Authentication Parameters Pro+

Pro Plan Required: Screenshot authenticated pages with session cookies or custom headers. Perfect for dashboards, admin panels, and private content.

Parameter Type Default Description
cookies JSON - Session cookies: [{"name":"x","value":"y"}]
headers JSON - Custom HTTP headers: {"Authorization":"Bearer x"}
stealth boolean false Bypass bot detection (Cloudflare, etc.)
stealth_level string standard basic, standard, or aggressive
headers_scope string same-origin Where to send custom headers: same-origin, same-site, all

Graceful Degradation

Auth parameters (cookies, headers, basic_auth) use graceful degradation:

  • If you don't have the required plan, the request still succeeds
  • The auth parameters are simply ignored
  • A header indicates which features were ignored: X-SnapForge-Features-Ignored

Device Frames

Parameter Type Default Description
frame string - Add device frame: browser, browser-dark, iphone-14, macbook-pro, ipad-pro, window-macos, window-windows

Customer S3 Storage Business

Business Plan Required: Upload screenshots directly to your own S3-compatible bucket (AWS S3, Cloudflare R2, DigitalOcean Spaces, MinIO).

Parameter Type Default Description
s3_bucket string - Your S3 bucket name
s3_region string - AWS region (e.g., us-east-1)
s3_access_key string - Your S3 access key
s3_secret_key string - Your S3 secret key
s3_endpoint string - Custom endpoint for R2/MinIO/DO Spaces
s3_path string - Path prefix in bucket (e.g., screenshots/)

Caching

SnapForge uses a two-tier caching system (Redis + Cloudflare R2 CDN) for blazing fast responses.

How It Works

  • cache=true (default): Check cache first. If HIT, return from CDN (~50ms). If MISS, capture and cache.
  • cache=false: Skip cache, capture fresh screenshot. Still updates cache in background.

Response Headers

X-Cache: HIT        # Served from cache
X-Cache: MISS       # Fresh capture, now cached
X-Cache: BYPASS     # cache=false was used
X-Cache-Age: 3600   # Cache age in seconds

Pro tip: For frequently accessed URLs, cached responses return in ~50ms compared to ~2.5s for fresh captures!

Response

Binary Response (default)

Returns the image directly. Cache HITs return 302 redirect to CDN.

Headers (Cache MISS)
HTTP/2 200 OK
Content-Type: image/png
X-Cache: MISS
[binary image data]
Headers (Cache HIT)
HTTP/2 302 Found
Location: https://pub-xxx.r2.dev/screenshots/abc123.png
X-Cache: HIT
X-Cache-Age: 1234

JSON Response

When response_type=json, returns a CDN URL.

JSON Response
{
  "url": "https://pub-xxx.r2.dev/screenshots/abc123.png",
  "cached": true,
  "cache_age": 1234,
  "format": "png",
  "width": 1280,
  "height": 720
}

Error Codes

All errors follow a consistent JSON format:

Error Response
{
  "error": {
    "code": "INVALID_URL",
    "message": "The provided URL is not valid"
  },
  "request_id": "req_abc123"
}
Code HTTP Description
INVALID_CREDENTIALS 401 Invalid or missing API key
RATE_LIMITED 429 Too many requests
INVALID_PARAMS 400 Parameter validation failed
SSRF_BLOCKED 403 URL blocked (internal/private IP)
REQUEST_TIMEOUT 504 Screenshot took too long
QUEUE_TIMEOUT 503 Service busy, retry later
SCREENSHOT_FAILED 500 Failed to capture screenshot

Rate Limits

Plan Screenshots/day Requests/min Price
Free 50 5 $0
Starter 500 15 $7/mo
Pro 3,000 30 $29/mo
Business 10,000 60 $49/mo

Rate Limit Headers

X-RateLimit-Limit: 15
X-RateLimit-Remaining: 12
X-RateLimit-Reset: 1701620400

Code Examples

cURL

Basic Screenshot
curl "https://api.snapforge.techyowls.io/v1/screenshot?url=https://github.com" \
  -H "X-API-Key: YOUR_API_KEY" \
  --output github.png

JavaScript (Node.js)

Node.js with fetch
const params = new URLSearchParams({
  url: 'https://github.com',
  width: 1280,
  height: 720,
  format: 'png'
});

const response = await fetch(
  `https://api.snapforge.techyowls.io/v1/screenshot?${params}`,
  { headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);

const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync('screenshot.png', buffer);

Python

Python with requests
import requests

response = requests.get(
    'https://api.snapforge.techyowls.io/v1/screenshot',
    params={
        'url': 'https://github.com',
        'width': 1280,
        'height': 720,
    },
    headers={'X-API-Key': 'YOUR_API_KEY'}
)

with open('screenshot.png', 'wb') as f:
    f.write(response.content)

Get CDN URL (JSON Response)

cURL - JSON response
curl "https://api.snapforge.techyowls.io/v1/screenshot?\
url=https://github.com&\
response_type=json" \
  -H "X-API-Key: YOUR_API_KEY"

# Returns:
# {"url":"https://pub-xxx.r2.dev/...","cached":true,...}

Force Fresh Screenshot

Bypass cache
curl "https://api.snapforge.techyowls.io/v1/screenshot?\
url=https://github.com&\
cache=false" \
  -H "X-API-Key: YOUR_API_KEY" \
  --output fresh.png

# X-Cache header will be: BYPASS

Screenshot with Cookies Pro+

Capture authenticated dashboard
# URL-encode the cookies JSON
COOKIES='[{"name":"session","value":"abc123","domain":".example.com"}]'
ENCODED=$(echo "$COOKIES" | jq -sRr @uri)

curl "https://api.snapforge.techyowls.io/v1/screenshot?\
url=https://app.example.com/dashboard&\
cookies=$ENCODED" \
  -H "X-API-Key: YOUR_API_KEY" \
  --output dashboard.png

Screenshot with Authorization Header Pro+

Capture protected API page
# URL-encode the headers JSON
HEADERS='{"Authorization":"Bearer eyJhbGciOiJIUzI1NiIs..."}'
ENCODED=$(echo "$HEADERS" | jq -sRr @uri)

curl "https://api.snapforge.techyowls.io/v1/screenshot?\
url=https://admin.example.com&\
headers=$ENCODED" \
  -H "X-API-Key: YOUR_API_KEY" \
  --output admin.png

Screenshot with Basic Auth Starter+

Capture staging site
# URL-encode the basic_auth JSON
AUTH='{"username":"admin","password":"secret"}'
ENCODED=$(echo "$AUTH" | jq -sRr @uri)

curl "https://api.snapforge.techyowls.io/v1/screenshot?\
url=https://staging.example.com&\
basic_auth=$ENCODED" \
  -H "X-API-Key: YOUR_API_KEY" \
  --output staging.png

HTML Render API Starter+

POST /v1/render

Render HTML content directly to screenshot without hosting it. Perfect for generating images from templates, invoices, charts, or dynamic content.

Request Body (JSON)
{
  "html": "<html><body><h1>Hello World</h1></body></html>",
  "base_url": "https://example.com",
  "width": 1280,
  "height": 720,
  "format": "png",
  "full_page": false,
  "frame": "browser"
}

Request Body Parameters

Parameter Type Description
html* string HTML content to render (required)
base_url string Base URL for relative links/assets
width integer Viewport width (default: 1280)
height integer Viewport height (default: 720)
format string png, jpeg, webp
full_page boolean Capture full scrollable content
frame string Add device frame (see Device Frames)
response_type string binary or json
cURL Example
curl "https://api.snapforge.techyowls.io/v1/render" \
  -X POST \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"html":"<h1>Hello</h1>","width":800,"height":600}' \
  --output render.png

Extract API Pro+

Extract structured data, page content, or answers from any webpage using AI. Three extraction modes — schema (structured JSON), markdown (page text), and prompt (ask a question) — with sync and async options.

Sync or Async: Set sync=true for an immediate blocking response (max 60s), or use the default async mode with webhook delivery or polling via GET /v1/extract/:id.

Extraction Modes

Mode Output Use Case
schema Structured JSON matching your schema Price monitoring, product data, lead enrichment
markdown Clean page text (no LLM, fastest) Content indexing, SEO auditing, text extraction
prompt Free-form AI answer to your question Q&A, summarization, sentiment analysis

Submit Extraction

POST /v1/extract
Request Body
{
  "url": "https://example.com/pricing",
  "mode": "schema",
  "schema": {
    "product_name": "string",
    "price": "number",
    "currency": "string",
    "in_stock": "boolean",
    "features": "array"
  },
  "sync": true,
  "webhook_url": "https://your-server.com/extract-callback",
  "webhook_secret": "your-hmac-secret",
  "options": {
    "width": 1280,
    "delay_ms": 2000,
    "full_page": false
  }
}

Request Parameters

Parameter Type Required Description
url string Yes URL to extract data from
mode string No auto, schema, markdown, or prompt. Default: auto (inferred from params)
schema object No Field names mapped to types: string, number, boolean, array. Max 20 fields. Required for schema mode.
prompt string No Question or instruction for the AI. Required for prompt mode. Max 2000 chars.
sync boolean No If true, blocks and returns result directly (max 60s). Default: false
webhook_url string No HTTPS URL to receive results. Must be public (no private IPs). Not needed if using sync or polling.
webhook_secret string No HMAC-SHA256 secret for webhook signature verification
options.width number No Viewport width (320-3840). Default: 1280
options.height number No Viewport height (240-2160). Default: 800
options.full_page boolean No Capture full scrollable page. Default: false
options.delay_ms number No Wait before capture in ms (0-10000). Default: 0
options.include_screenshot boolean No Include screenshot URL in result. Default: true

Response — Sync mode (sync=true) returns 200 with full result:

Sync Response (200 OK) — Schema Mode
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "complete",
  "mode": "schema",
  "data": { "product_name": "Pro Plan", "price": 29 },
  "confidence": 0.92,
  "screenshot_url": "https://screenshots.snapforge.techyowls.io/extractions/550e8400.png",
  "extraction_time_ms": 2500,
  "model": "llama3.1:8b"
}
Sync Response (200 OK) — Markdown Mode
{
  "job_id": "...",
  "status": "complete",
  "mode": "markdown",
  "content": "# Page Title\n\nPage content extracted as clean text...",
  "extraction_time_ms": 280
}
Sync Response (200 OK) — Prompt Mode
{
  "job_id": "...",
  "status": "complete",
  "mode": "prompt",
  "answer": "The cheapest plan is the Starter plan at $7/month.",
  "extraction_time_ms": 1800
}

Async mode (default) returns 202 Accepted — poll with GET /v1/extract/:id or wait for webhook:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing",
  "created_at": "2025-03-15T10:30:00Z"
}

Check Status / Poll Results

GET /v1/extract/:id

Poll job status. Returns the same response format as sync mode when complete. Works with or without a webhook.

Webhook Payload

When extraction completes, SnapForge POSTs the result to your webhook_url:

Success Payload
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "complete",
  "data": {
    "product_name": "Pro Plan",
    "price": 29,
    "currency": "USD",
    "in_stock": true,
    "features": ["Stealth mode", "Custom headers"]
  },
  "confidence": 0.92,
  "screenshot_url": "https://screenshots.snapforge.techyowls.io/extractions/550e8400.png",
  "extraction_time_ms": 8500,
  "model": "llama3.2-vision",
  "completed_at": "2025-03-15T10:30:08Z"
}
Failure Payload
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "failed",
  "error": "Screenshot capture timed out",
  "completed_at": "2025-03-15T10:30:30Z"
}

Webhook Signature Verification

If you provide a webhook_secret, SnapForge signs each webhook with HMAC-SHA256. Verify using the X-Webhook-Signature header:

Node.js Verification
const crypto = require('crypto');

function verifyWebhook(body, signature, timestamp, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(timestamp + '.' + body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature), Buffer.from(expected)
  );
}

cURL Example

cURL
# Sync mode — get result immediately
curl -X POST https://api.snapforge.techyowls.io/v1/extract \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/pricing",
    "mode": "schema",
    "schema": {
      "product_name": "string",
      "price": "number",
      "in_stock": "boolean"
    },
    "sync": true
  }'

Python Example

Python
import requests

# Sync mode — result in one call
response = requests.post(
    "https://api.snapforge.techyowls.io/v1/extract",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "url": "https://example.com/pricing",
        "mode": "schema",
        "schema": {
            "product_name": "string",
            "price": "number",
            "in_stock": "boolean"
        },
        "sync": True
    }
)

data = response.json()
print(data["data"])  # {"product_name": "Pro Plan", "price": 29, ...}

Rate Limits: Pro: 10 requests/minute, 500/day. Business: 30 requests/minute, 2,000/day. Processing time: ~300ms (markdown), 2-5s (schema/prompt).

Batch Extract

POST /v1/extract/batch

Submit 1-50 URLs in a single request. Returns 202 with a batch_id. Poll with GET /v1/extract/batch/:id for per-item results.

Batch Request
{
  "urls": [
    { "url": "https://example.com/page-1" },
    { "url": "https://example.com/page-2", "schema": { "title": "string" } }
  ],
  "mode": "markdown",
  "webhook_url": "https://your-server.com/batch-callback"
}

Per-item schema and prompt override the batch-level defaults. Each URL in the batch counts as 1 request toward your daily limit.

Batch API Pro+

Process multiple URLs in a single request with webhook notification when complete. Perfect for capturing many pages efficiently.

Create Batch

POST /v1/batch
Request Body
{
  "urls": [
    { "url": "https://example.com" },
    { "url": "https://github.com", "options": { "width": 1920 } }
  ],
  "webhook_url": "https://your-server.com/webhook",
  "default_options": {
    "format": "png",
    "width": 1280,
    "height": 720
  }
}

Other Batch Endpoints

Method Endpoint Description
GET /v1/batch/:id Get batch status and results
DELETE /v1/batch/:id Cancel a running batch
GET /v1/batches List all your batches
Webhook Payload
{
  "batch_id": "abc123",
  "status": "completed",
  "total": 10,
  "succeeded": 9,
  "failed": 1,
  "results": [
    { "url": "https://example.com", "status": "success", "screenshot_url": "..." }
  ],
  "duration_ms": 15000
}

Best Practices

Leverage caching

Default cache=true returns cached screenshots in ~50ms. Only use cache=false when you need fresh content.

Use JSON response for frontend apps

Set response_type=json to get a CDN URL. Display it directly in <img src="..."> for best performance.

Add delay for dynamic content

For SPAs or pages with JavaScript animations, use delay=2000 to wait for content to load.

Use clean parameters

Remove distracting elements with clean=true to hide cookie banners, chat widgets, and popups.

Ready to get started?

Sign up for free - no credit card required. 50 screenshots/day included!

Get Free API Key