Screenshot

Use the Screenshot APIs to capture URLs or HTML snippets as PNG/JPEG/WEBP images. Each request costs credits proportional to image size and responds with a signed S3 URL (valid for 30 minutes).


POST/v1/screenshot/url

Take a screenshot of a URL

Supply a public HTTPS URL to render.

Required attributes

  • Name
    url
    Type
    string
    Description

    Fully-qualified HTTPS URL to capture.

Optional attributes

  • Name
    callback_url
    Type
    string
    Description

    HTTPS endpoint to notify once the capture finishes (optional).

  • Name
    engine_options
    Type
    object
    Description

    Screenshot engine controls.

    • Name
      timeout
      Type
      integerDefault: 30000
      Description

      Timeout in milliseconds before aborting navigation.

    • Name
      waitForNetworkToIdle
      Type
      booleanDefault: false
      Description

      When true, waits for network to be idle before capturing.

  • Name
    options
    Type
    object
    Description

    Visual output options.

    • Name
      type
      Type
      stringDefault: png
      Description

      Output image type (png, jpeg, or webp).

    • Name
      fullPage
      Type
      booleanDefault: false
      Description

      Capture the full scroll height instead of the viewport height.

    • Name
      captureBeyondViewport
      Type
      booleanDefault: false
      Description

      Attempt to capture content beyond the viewport (Chromium experimental flag).

    • Name
      omitBackground
      Type
      booleanDefault: false
      Description

      Make the background transparent (only for PNG/WebP).

    • Name
      quality
      Type
      integer
      Description

      JPEG quality (1-100). Only applies when type is jpeg.

    • Name
      clip
      Type
      object
      Description

      Crop rectangle in CSS pixels.

      • Name
        x
        Type
        integer
        Description
        Left offset.
      • Name
        y
        Type
        integer
        Description
        Top offset.
      • Name
        width
        Type
        integer
        Description
        Width of the clip.
      • Name
        height
        Type
        integer
        Description
        Height of the clip.
      • Name
        scale
        Type
        numberDefault: 1
        Description
        Device scale factor (usually 1 or 2).

Request

POST
/v1/screenshot/url
curl -X POST https://api.pdfloom.com/v1/screenshot/url \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "url": "https://example.com",
    "callback_url": "https://example.com/webhook",
    "options": {
      "type": "png",
      "fullPage": true
    }
  }'

Response

{
  "success": true,
  "response": "https://pdfloom-processed.s3.amazonaws.com/generated/ss/7c9b1f9c.png?...",
  "fileSize": 65740
}

POST/v1/screenshot/html

Take a screenshot of HTML content

Post raw HTML or templated markup and receive an image.

Required attributes

  • Name
    content
    Type
    string
    Description

    HTML string to render (max 512 KB).

Optional attributes

  • Name
    assets
    Type
    array
    Description

    Additional resources (CSS/JS) referenced by content. Maximum 10 assets, 200 KB each.

  • Name
    callback_url
    Type
    string
    Description

    HTTPS webhook to notify on completion.

  • Name
    options
    Type
    object
    Description

    Same as /v1/screenshot/url (type, fullPage, clip, quality, etc.).

  • Name
    engine_options
    Type
    object
    Description

    Browser-level tuning options (timeout, waitForNetworkToIdle).

cURL

curl -X POST https://api.pdfloom.com/v1/screenshot/html \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "content": "<html><body><h1>Screenshot me</h1></body></html>",
    "options": {
      "type": "png",
      "fullPage": false
    }
  }'
import requests, uuid

response = requests.post(
  'https://api.pdfloom.com/v1/screenshot/html',
  headers={
    'Authorization': 'Bearer YOUR_API_TOKEN',
    'Content-Type': 'application/json',
    'Idempotency-Key': str(uuid.uuid4()),
  },
  json={
    'content': '<html><body><h1>Screenshot me</h1></body></html>',
    'options': {'type': 'jpeg', 'quality': 80},
  },
)
print(response.json())

Authenticated capture (screenshot)

Authenticated capture lets the renderer log in on your behalf before taking a screenshot. Add an auth block when the target page is behind login (headers, cookies, form login, or a token-injection script). HTTPS is required for auth URLs. Script-based auth can be disabled by your workspace admin.

Size & Rate Limits

  • HTML content: Maximum 512 KB (524,288 bytes)
  • Assets: Maximum 10 assets per request, 200 KB each
  • Auth scripts: Maximum 2,000 characters per script, up to 3 scripts
  • Auth headers/cookies: Maximum 20 headers or cookies
  • Auth wait timeout: Maximum 60 seconds
  • Rate limiting: Auth capture requests limited to 30 per minute

Security Safeguards

  • All callback URLs must use HTTPS
  • Auth capture URLs must use HTTPS (configurable via AUTH_REQUIRE_HTTPS)
  • Script-based auth can be disabled workspace-wide via AUTH_ALLOW_SCRIPT=false
  • Private/local IPs are blocked by default to prevent SSRF attacks
  • Name
    auth.type
    Type
    string
    Description

    header, bearer, basic, cookie, form, or script.

  • Name
    auth.headers
    Type
    object
    Description

    Custom headers map (when type=header).

  • Name
    auth.token
    Type
    string
    Description

    Bearer token (when type=bearer).

  • Name
    auth.username
    Type
    string
    Description

    Username (when type=basic).

  • Name
    auth.password
    Type
    string
    Description

    Password (when type=basic).

  • Name
    auth.cookies
    Type
    array
    Description

    Cookies with name, value, domain, optional path, secure, httpOnly (when type=cookie).

  • Name
    auth.login_url
    Type
    string
    Description

    HTTPS login URL (when type=form).

  • Name
    auth.credentials
    Type
    object
    Description

    Key/value pairs to fill into selectors (when type=form).

  • Name
    auth.selectors
    Type
    object
    Description

    CSS selectors for fields + submit button (when type=form).

  • Name
    auth.scripts
    Type
    array
    Description

    JS snippets to set tokens/localStorage (when type=script).

  • Name
    auth.wait
    Type
    object
    Description

    Optional { selector, waitUntil, timeoutMs } to pause after auth before capture.

Example — bearer auth + wait:

cURL

curl -X POST https://api.pdfloom.com/v1/screenshot/url \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://app.example.com/dashboard",
    "auth": {
      "type": "bearer",
      "token": "YOUR_SESSION_TOKEN",
      "wait": { "selector": "#chart", "waitUntil": "networkidle2" }
    },
    "options": { "type": "png", "fullPage": true }
  }'

Example — form login:

await fetch('https://api.pdfloom.com/v1/screenshot/url', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://app.example.com/reports',
    auth: {
      type: 'form',
      login_url: 'https://app.example.com/login',
      credentials: { email: 'user@example.com', password: 's3cret!' },
      selectors: { email: '#email', password: '#password', submit: 'button[type=submit]' },
      wait: { selector: '#reports-table', waitUntil: 'networkidle2', timeoutMs: 15000 }
    },
    options: { type: 'jpeg', quality: 90 }
  })
})

Webhooks / Callbacks

When you provide a callback_url, PDF-Loom will send an HTTP POST request to that URL once the screenshot is complete (either successfully or with an error).

Callback Request Format

The callback POST request includes:

Headers:

  • Content-Type: application/json
  • X-PDFLoom-Request-Id: req_abc123 - The original request ID for correlation
  • X-PDFLoom-Signature: sha256=... - HMAC signature (when CALLBACK_SIGNING_SECRET is configured)

Payload (Success):

{
  "success": true,
  "request_id": "req_abc123",
  "file_url": "https://pdfloom-processed.s3.amazonaws.com/generated/ss/...",
  "file_size": 65740,
  "credits_consumed": 1,
  "completed_at": "2026-02-02T10:30:00Z"
}

Payload (Error):

{
  "success": false,
  "request_id": "req_abc123",
  "error_code": "GENERATOR_FAILED",
  "message": "Generator service reported failure",
  "failed_at": "2026-02-02T10:30:00Z"
}

Verifying Webhook Signatures

If your environment has CALLBACK_SIGNING_SECRET configured, verify the signature to ensure the webhook is authentic:

import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected_signature = 'sha256=' + hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected_signature)

# In your webhook handler:
signature = request.headers.get('X-PDFLoom-Signature')
is_valid = verify_webhook(request.body, signature, os.getenv('CALLBACK_SECRET'))

if not is_valid:
    return 'Invalid signature', 401

Retry Behavior

  • Callbacks are sent once after screenshot completion
  • No automatic retries are performed
  • Your callback endpoint should respond with 2xx status code to acknowledge receipt
  • Callback requests timeout after 30 seconds
  • Failed callbacks are logged but do not affect the screenshot result

Error responses

Screenshot endpoints return the same structure as convert. Expect HTTP 4xx for validation issues and 503 when the renderer is temporarily unavailable.

{
  "success": false,
  "error_code": "PAYMENT_REQUIRED",
  "message": "Insufficient credits.",
  "available_credits": 0,
  "required_credits": 1
}
{
  "success": false,
  "message": "The options.type field must be one of: png, jpeg, webp.",
  "status": 422
}
{
  "success": false,
  "message": "Generator service unavailable.",
  "status": 503
}

Error Handling

When screenshot capture fails, the API returns a JSON error response with a specific error code.

Common Screenshot Errors

SCREENSHOT-001: Screenshot Failed

This error occurs when the screenshot capture process fails. Common causes include:

  • Invalid image format requested
  • Page rendering issues
  • Viewport configuration errors
  • Resource loading timeout
{
  "success": false,
  "error_code": "SCREENSHOT-001",
  "message": "Screenshot capture failed",
  "details": "Invalid viewport configuration"
}

Solutions:

  • Use only supported formats: png, jpeg, webp
  • Verify viewport dimensions are reasonable (width/height > 0)
  • Check that the page renders correctly in a browser
  • Simplify page content if it's too complex
  • Increase timeout in engine_options.timeout if needed

Retry Behavior

The API automatically handles retries for you:

  • Automatically retried: Network timeouts, temporary service issues
  • Not retried: Screenshot failures (SCREENSHOT-001), validation errors

If you receive a SCREENSHOT-001 error, the issue is likely with the content or configuration. Fix the underlying issue before retrying.

Complete Error Reference

For a complete list of error codes, HTTP status codes, and detailed debugging guidance, see the Errors page.

Was this page helpful?