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 "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.
X-API-Key: sk_live_xxxxxxxxxxxxx
Get your API key: Sign up for free - no credit card required. 50 screenshots/day included!
Take Screenshot
/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.
HTTP/2 200 OK
Content-Type: image/png
X-Cache: MISS
[binary image data]
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.
{
"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": {
"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
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)
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
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 "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
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+
# 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+
# 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+
# 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+
/v1/render
Render HTML content directly to screenshot without hosting it. Perfect for generating images from templates, invoices, charts, or dynamic content.
{
"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 "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
/v1/extract
{
"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:
{
"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"
}
{
"job_id": "...",
"status": "complete",
"mode": "markdown",
"content": "# Page Title\n\nPage content extracted as clean text...",
"extraction_time_ms": 280
}
{
"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
/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:
{
"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"
}
{
"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:
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
# 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
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
/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.
{
"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
/v1/batch
{
"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 |
{
"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