API Documentation

Everything you need to capture website screenshots programmatically.

Getting Started

Start capturing screenshots in three simple steps.

1

Create an account

Sign up for a free account. No credit card required.

2

Copy your API key

Go to your dashboard and copy your API key.

3

Make your first request

Use the example below to capture your first screenshot.

First request
curl -X GET "https://api.fastscreenshotapi.com/v1/screenshot?url=https://example.com" \
  -H "X-Api-Key: your_api_key" \
  --output screenshot.png

Authentication

All API requests require authentication. There are three ways to authenticate.

X-Api-Key header Recommended

Pass your API key via the X-Api-Key header.

bash
curl "https://api.fastscreenshotapi.com/v1/screenshot?url=https://example.com" \
  -H "X-Api-Key: fsa_your_api_key"

Query parameter

Pass your API key as an api_key query parameter. Useful for embedding in <img> tags.

html
<img src="https://api.fastscreenshotapi.com/v1/screenshot?url=https://example.com&api_key=fsa_your_api_key" />

Bearer token

For dashboard API endpoints, use a Bearer token in the Authorization header.

bash
curl "https://api.fastscreenshotapi.com/v1/account" \
  -H "Authorization: Bearer your_access_token"

Screenshot Endpoint

GET /v1/screenshot

Pass parameters as query strings. Ideal for embedding in <img> tags.

bash
curl "https://api.fastscreenshotapi.com/v1/screenshot?url=https://example.com&format=webp&full_page=true" \
  -H "X-Api-Key: fsa_your_api_key" \
  --output screenshot.webp

POST /v1/screenshot

Send parameters as a JSON body for full control over all options.

bash
curl -X POST "https://api.fastscreenshotapi.com/v1/screenshot" \
  -H "X-Api-Key: fsa_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "format": "webp",
    "full_page": true,
    "viewport_width": 1440,
    "dark_mode": true
  }' \
  --output screenshot.webp

Parameters

All parameters for the screenshot endpoint.

ParameterTypeDefaultPlanDescription
urlstringrequiredFreeURL to capture
formatstringpngFreeOutput format: png, jpeg, webp
qualityinteger85FreeImage quality for JPEG/WebP (1-100)
full_pagebooleanfalseFreeCapture entire scrollable page
mobilebooleanfalseFreeUse mobile viewport and user agent
block_cookie_bannersbooleantrueFreeAuto-dismiss cookie/GDPR banners
block_adsbooleanfalseFreeBlock ad scripts
scroll_to_bottombooleantrueFreeAuto-scroll for lazy-loaded content
delayinteger0FreeExtra delay after page load in ms (0-10000)
wait_for_timeoutinteger30000FreeMax wait time in ms (1000-60000)
cache_ttlinteger86400FreeCache duration in seconds (0 = no cache, max 604800)
response_typestringbinaryFreeResponse format: binary, json, url
viewport_widthinteger1920Starter+Browser viewport width (320-3840)
viewport_heightinteger1080Starter+Browser viewport height (240-2160)
device_scale_factorfloat1Starter+Pixel density (2 for Retina)
custom_cssstringStarter+CSS to inject before capture (max 5000 chars)
hide_selectorsarray[]Starter+CSS selectors to hide (max 10)
dark_modebooleanfalsePro+Prefer dark color scheme
custom_headersobjectPro+Custom HTTP headers to send (max 10)
cookiesarrayPro+Cookies to set: [{name, value, domain}]
htmlstringPro+HTML to render instead of URL (max 1MB, POST only)
webhook_urlstringPro+URL for async result delivery (async endpoint only)
webhook_secretstringPro+HMAC-SHA256 secret for webhook signature verification
upload_toobjectPro+External S3/R2 storage config (async endpoint only)

Response Types

Control the response format with the response_type parameter.

binary (default)

Returns raw image data with the appropriate Content-Type header (image/png, image/jpeg, or image/webp).

json

Returns a JSON object with a base64-encoded screenshot and metadata.

response_type=json
{
  "data": {
    "screenshot": "iVBORw0KGgoAAAANSUhEUgAA...",
    "format": "png",
    "width": 1920,
    "height": 1080,
    "file_size": 284729
  },
  "metadata": {
    "url": "https://example.com",
    "title": "Example Domain",
    "request_id": "req_abc123",
    "cached": false,
    "duration_ms": 1240
  }
}

url

Returns a JSON object with a temporary URL to the screenshot (valid for 1 hour).

response_type=url
{
  "data": {
    "url": "https://api.fastscreenshotapi.com/screenshots/req_abc123.png?expires=1700000000&sig=...",
    "format": "png",
    "width": 1920,
    "height": 1080,
    "file_size": 284729,
    "expires_at": "2024-11-15T12:00:00Z"
  },
  "metadata": {
    "url": "https://example.com",
    "title": "Example Domain",
    "request_id": "req_abc123",
    "cached": false,
    "duration_ms": 1240
  }
}

Response Headers

Every response includes these headers with request metadata.

HeaderDescription
X-Request-IdUnique request identifier for debugging and support
X-RateLimit-LimitMaximum requests allowed per minute
X-RateLimit-RemainingRemaining requests in the current minute window
X-RateLimit-ResetUnix timestamp when the rate limit resets
X-Quota-LimitTotal monthly screenshot quota for your plan
X-Quota-UsedScreenshots used in the current billing period
X-CacheCache status: HIT (served from cache) or MISS (fresh capture)

Caching

Screenshots are cached to improve performance and reduce redundant captures.

  • Default cache duration is 24 hours (86400 seconds).
  • Same URL + same parameters = instant cache hit (~300ms response time).
  • Cached requests do not count against your monthly quota.
  • Use cache_ttl=0 to disable caching. Maximum TTL is 7 days (604800 seconds).

Anti-bot Bypass

Many websites use bot detection (Cloudflare, DataDome, PerimeterX) that blocks headless browsers. On Pro+ plans, FastScreenshotAPI automatically uses stealth mode with ISP residential proxies to bypass these protections.

  • Stealth browser fingerprinting — mimics real user browsers.
  • ISP residential proxies — real IP addresses, not datacenter IPs.
  • Automatic — no extra parameters needed. Just works on Pro and Business plans.

Plan Requirements

Some features require a specific plan. If you use a restricted feature on a lower plan, the API returns a 403 FEATURE_RESTRICTED error.

PlanFeatures Included
FreeCore parameters: url, format, quality, full_page, mobile, block_cookie_banners, block_ads, scroll_to_bottom, delay, cache_ttl, response_type
Starter++ viewport_width, viewport_height, device_scale_factor, custom_css, hide_selectors
Pro++ dark_mode, custom_headers, cookies, html, webhook_url, webhook_secret, upload_to, anti-bot bypass, async endpoint
Business+ Priority rendering queue

Code Examples

Complete, copy-pasteable examples in popular languages.

cURL
curl -X POST "https://api.fastscreenshotapi.com/v1/screenshot" \
  -H "X-Api-Key: fsa_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "format": "webp",
    "quality": 90,
    "full_page": true,
    "viewport_width": 1440,
    "block_cookie_banners": true
  }' \
  --output screenshot.webp
Node.js
const response = await fetch("https://api.fastscreenshotapi.com/v1/screenshot", {
  method: "POST",
  headers: {
    "X-Api-Key": "fsa_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://example.com",
    format: "webp",
    quality: 90,
    full_page: true,
    viewport_width: 1440,
    block_cookie_banners: true,
  }),
});

const buffer = await response.arrayBuffer();
const fs = await import("fs");
fs.writeFileSync("screenshot.webp", Buffer.from(buffer));

console.log("Request ID:", response.headers.get("X-Request-Id"));
console.log("Cached:", response.headers.get("X-Cache"));
Python
import requests

response = requests.post(
    "https://api.fastscreenshotapi.com/v1/screenshot",
    headers={"X-Api-Key": "fsa_your_api_key"},
    json={
        "url": "https://example.com",
        "format": "webp",
        "quality": 90,
        "full_page": True,
        "viewport_width": 1440,
        "block_cookie_banners": True,
    },
)

with open("screenshot.webp", "wb") as f:
    f.write(response.content)

print("Request ID:", response.headers["X-Request-Id"])
print("Cached:", response.headers["X-Cache"])
PHP
$ch = curl_init("https://api.fastscreenshotapi.com/v1/screenshot");

curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "X-Api-Key: fsa_your_api_key",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "url" => "https://example.com",
        "format" => "webp",
        "quality" => 90,
        "full_page" => true,
        "viewport_width" => 1440,
        "block_cookie_banners" => true,
    ]),
]);

$response = curl_exec($ch);
curl_close($ch);

file_put_contents("screenshot.webp", $response);
HTML (img tag)
<!-- Direct embedding — uses your API key as a query parameter -->
<img
  src="https://api.fastscreenshotapi.com/v1/screenshot?url=https://example.com&format=webp&viewport_width=1440&api_key=fsa_your_api_key"
  alt="Screenshot of example.com"
  loading="lazy"
/>

Async Screenshots

Use async screenshots for heavy pages, batch processing, serverless environments, or when you need webhook notifications.

POST /v1/screenshot/async

Submit a screenshot job and receive a job ID. The screenshot will be processed in the background.

Async request
curl -X POST https://api.fastscreenshotapi.com/v1/screenshot/async \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "format": "png",
    "full_page": true,
    "webhook_url": "https://your-server.com/webhook",
    "webhook_secret": "your-hmac-secret"
  }'

Response (202)

Async response
{
    "job_id": "job_cZ1DADXGyzNM",
    "status": "queued",
    "status_url": "https://api.fastscreenshotapi.com/v1/screenshot/status/job_cZ1DADXGyzNM",
    "estimated_time_ms": 30000
}

Checking Status

Use GET /v1/screenshot/status/{jobId} to check the status of a job. A job can be in one of three statuses:

  • queued — the job is waiting to be picked up by a worker.
  • processing — the browser is loading the page and capturing the screenshot.
  • completed / failed — the job finished successfully or encountered an error.

Polling vs Webhooks

For production use, we recommend webhooks — they deliver results instantly without repeated API calls. Use polling only for testing or when webhooks are not feasible.

Webhook Verification

Webhooks are signed with HMAC-SHA256. The signature is sent in the X-Webhook-Signature header. Always verify the signature before processing webhook payloads.

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

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const expected = crypto
    .createHmac('sha256', 'your-webhook-secret')
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (signature !== expected) {
    return res.status(401).send('Invalid signature');
  }

  const { job_id, status, screenshot_url } = req.body;
  console.log(`Job ${job_id}: ${status}`);
  res.status(200).send('OK');
});
Python
import hmac, hashlib

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Webhook-Signature')
    expected = hmac.new(
        b'your-webhook-secret',
        request.data,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        abort(401)

    data = request.json
    print(f"Job {data['job_id']}: {data['status']}")
    return 'OK', 200

HTML Rendering

Render custom HTML as a screenshot — perfect for invoices, OG images, email templates, and reports.

  • Only available via POST (not GET).
  • html and url are mutually exclusive — provide one or the other.
  • Maximum HTML size: 1 MB.
  • Works with all response_type options (binary, json, url).
  • Runs in an isolated browser context for security.
HTML rendering
curl -X POST https://api.fastscreenshotapi.com/v1/screenshot \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<html><body><h1>Invoice #123</h1><p>Total: $500</p></body></html>",
    "format": "png",
    "response_type": "json"
  }'

External Storage Upload

Upload screenshots directly to your own S3-compatible bucket instead of using our temporary storage.

  • Supported providers: AWS S3, Cloudflare R2, DigitalOcean Spaces, Backblaze B2, MinIO, Wasabi.
  • Minimum permissions: s3:PutObject, s3:PutObjectAcl.
  • Available with async screenshots.
Upload to S3
curl -X POST https://api.fastscreenshotapi.com/v1/screenshot/async \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "upload_to": {
      "type": "s3",
      "bucket": "my-screenshots",
      "region": "eu-west-1",
      "access_key": "AKIA...",
      "secret_key": "...",
      "path": "screenshots/"
    }
  }'

For one-time bucket configuration, visit your dashboard storage settings.

Error Codes

When a request fails, the API returns a JSON error response with a machine-readable code, a human-readable message, and a suggestion to help you resolve the issue.

CodeHTTP StatusDescriptionSuggestion
INVALID_URL400URL is malformed or unreachableProvide a valid URL starting with http:// or https://
INVALID_PARAMS400Validation errorCheck parameter values against docs
UNAUTHORIZED401Missing or invalid API keyPass API key via X-Api-Key header
ACCOUNT_SUSPENDED403Account suspendedContact support
PRIVATE_IP403URL resolves to private IPOnly publicly accessible URLs allowed
FEATURE_RESTRICTED403Feature not available on your planUpgrade to a higher plan to access this feature
QUOTA_EXCEEDED429Monthly quota reachedUpgrade plan for more screenshots
RATE_LIMITED429Too many requests per minuteWait and retry, check X-RateLimit-Reset header
PAGE_NOT_FOUND422Target URL returned 404Check if the URL is correct
SSL_ERROR422Target has SSL issuesCheck target site's SSL certificate
BLOCKED_BY_SITE422Target blocked the requestSite has bot protection
SCREENSHOT_TIMEOUT504Page load timeoutIncrease wait_for_timeout or simplify the target page
SCREENSHOT_FAILED502Capture failedRetry the request
SERVICE_OVERLOADED503All containers busyRetry with exponential backoff
INTERNAL_ERROR500Server errorContact support

Error Response Format

Every error response follows the same structure:

json
{
    "error": true,
    "code": "SCREENSHOT_TIMEOUT",
    "message": "Page did not finish loading within the timeout.",
    "suggestion": "Try increasing wait_for_timeout or use wait_for: 'domcontentloaded'.",
    "documentation_url": "https://fastscreenshotapi.com/docs#error-codes"
}