Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.screenshotly.dev/llms.txt

Use this file to discover all available pages before exploring further.

The Screenshotly API uses standard HTTP status codes to indicate success or failure.

Status code overview

RangeMeaning
2xxThe request succeeded
4xxThe request failed due to a client error
5xxThe request failed due to a server error

Error response format

All error responses return a JSON body with an error object containing code and message fields:
{
  "error": {
    "code": "invalid_options",
    "message": "Validation failed."
  }
}
Some errors include a details field with additional context:
{
  "error": {
    "code": "invalid_options",
    "message": "Validation failed.",
    "details": {
      "url": "\"url\" is required"
    }
  }
}

Error codes

StatusCodeDescription
401missing_api_keyNo API key provided. Pass it via the X-API-Key header or api_key query parameter.
401invalid_api_keyThe provided API key is invalid or has been revoked.
401unauthorizedAuthentication required. Provide a valid API key.
402usage_limit_exceededMonthly screenshot limit reached. Upgrade your subscription at the dashboard.
403forbiddenYou do not have permission to access this resource.
404not_foundThe requested resource (e.g., screenshot ID) was not found.
422invalid_optionsValidation failed. Check the details field for specific parameter errors.
422invalid_urlThe provided URL is not valid. Ensure it includes a protocol (e.g., https://).
422selector_not_foundThe specified CSS selector was not found on the page. Only returned when error_on_selector_not_found is true.
429rate_limit_exceededToo many requests per minute. See rate limits.
500render_failedScreenshot rendering failed. The target page may have caused an error.
500internal_errorAn unexpected server error occurred. Retry the request. If it persists, contact support.
502host_errorCould not reach the target URL. The site may be down or blocking requests.
503service_unavailableThe screenshot service is starting up. Retry in a few seconds.
504navigation_timeoutPage navigation timed out. Try increasing the navigation_timeout or timeout options.

Handling errors

Python

import requests

response = requests.post(
    'https://api.screenshotly.dev/v1/capture',
    headers={'X-API-Key': API_KEY, 'Content-Type': 'application/json'},
    json={'url': 'https://example.com', 'options': {'response_type': 'json'}}
)

if response.status_code == 401:
    print('Check your API key')
elif response.status_code == 402:
    print('Monthly limit reached — upgrade your plan')
elif response.status_code == 429:
    print('Rate limited — retry after a delay')
elif response.status_code >= 400:
    error = response.json()['error']
    print(f"Error [{error['code']}]: {error['message']}")

JavaScript

const response = await fetch('https://api.screenshotly.dev/v1/capture', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.SCREENSHOTLY_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com',
    options: { response_type: 'json' },
  }),
});

if (!response.ok) {
  const { error } = await response.json();
  console.error(`Error [${error.code}]: ${error.message}`);

  if (error.details) {
    console.error('Details:', error.details);
  }
}

Retry strategy

For transient errors (429, 5xx), implement exponential backoff:
async function captureWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch('https://api.screenshotly.dev/v1/capture', {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.SCREENSHOTLY_API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ url, options }),
    });

    if (response.ok) return response;

    // Don't retry client errors (except 429)
    if (response.status >= 400 && response.status < 500 && response.status !== 429) {
      const { error } = await response.json();
      throw new Error(`${error.code}: ${error.message}`);
    }

    // Wait before retrying: 1s, 2s, 4s
    const delay = Math.pow(2, attempt) * 1000;
    await new Promise(resolve => setTimeout(resolve, delay));
  }

  throw new Error('Max retries exceeded');
}