Skip to main content

Errors

This document describes all error responses you may encounter when using the BoltShot API, along with their causes and solutions.

Error Response Format​

All error responses follow this standardized format:

{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": "Additional error details (optional, can be string, array, or object)"
}
}

Error Codes​

Error codes are standardized across the API for programmatic handling:

  • VALIDATION_ERROR - Validation failed
  • INVALID_INPUT - Invalid input provided
  • MISSING_REQUIRED_FIELD - Required field is missing
  • INVALID_FORMAT - Invalid format
  • AUTHENTICATION_ERROR - Authentication failed
  • INVALID_TOKEN - Invalid authentication token
  • TOKEN_EXPIRED - Token has expired
  • INVALID_CREDENTIALS - Invalid login credentials
  • API_KEY_REQUIRED - API key is required
  • INVALID_API_KEY - Invalid API key
  • API_KEY_EXPIRED - API key has expired
  • AUTHORIZATION_ERROR - Authorization failed
  • INSUFFICIENT_PERMISSIONS - Insufficient permissions
  • ACCESS_DENIED - Access denied
  • EMAIL_NOT_VERIFIED - Email not verified
  • TARGET_PROTECTED - Target page is protected by anti-bot verification
  • NOT_FOUND - Resource not found
  • RESOURCE_NOT_FOUND - Requested resource not found
  • ROUTE_NOT_FOUND - API route not found
  • CONFLICT_ERROR - Resource conflict
  • DUPLICATE_ENTRY - Duplicate entry exists
  • PAYMENT_ERROR - Payment error
  • INSUFFICIENT_CREDITS - Insufficient credits
  • SUBSCRIPTION_REQUIRED - Subscription required
  • RATE_LIMIT_EXCEEDED - Rate limit exceeded
  • SERVER_ERROR - Server error
  • DATABASE_ERROR - Database error
  • INTERNAL_ERROR - Internal error
  • OPERATION_FAILED - Operation failed
  • OPENAI_ANALYSIS_FAILED - OpenAI analysis request failed

HTTP Status Codes​

200 OK​

Success - Request completed successfully.

201 Created​

Success - Resource created successfully.

400 Bad Request​

Client Error - The request was malformed or invalid.

Common Causes:

  • Missing required parameters
  • Invalid parameter types
  • Invalid URL format
  • Validation errors

Example:

{
"success": false,
"error": {
"code": "MISSING_REQUIRED_FIELD",
"message": "URL is required for screenshot generation."
}
}

Solution:

  • Check that all required parameters are included
  • Verify parameter types match the expected format
  • Ensure URLs are properly formatted and accessible

401 Unauthorized​

Authentication Error - Authentication failed or is missing.

Common Causes:

  • Missing authentication token/key
  • Invalid or expired token
  • Invalid API key
  • Expired API key

Examples:

Missing Token:

{
"success": false,
"error": {
"code": "API_KEY_REQUIRED",
"message": "Access token required"
}
}

Invalid Token:

{
"success": false,
"error": {
"code": "INVALID_TOKEN",
"message": "Invalid token"
}
}

Expired Token:

{
"success": false,
"error": {
"code": "TOKEN_EXPIRED",
"message": "Token expired"
}
}

Invalid API Key:

{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid API key"
}
}

Expired API Key:

{
"success": false,
"error": {
"code": "API_KEY_EXPIRED",
"message": "API key expired"
}
}

Solution:

  • Verify authentication header is included
  • Check token/key is correct and not expired
  • Re-authenticate to get a new token
  • Create a new API key if needed

402 Payment Required​

Billing Error - Insufficient credits or subscription required.

Example:

{
"success": false,
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits. Please upgrade your plan."
}
}

Solution:

  • Check your account credits
  • Upgrade your subscription plan

403 Forbidden​

Authorization Error - Authenticated but lacks permission.

Common Cause:

  • Access denied to organization
  • Target page is protected by anti-bot verification (e.g., reCAPTCHA, hCaptcha, Cloudflare challenge)

Examples:

Organization Access:

{
"success": false,
"error": {
"code": "ACCESS_DENIED",
"message": "Access denied to organization"
}
}

Protected Target (Screenshot API):

{
"success": false,
"error": {
"code": "TARGET_PROTECTED",
"message": "Screenshot failed",
"details": {
"requestId": "uuid",
"message": "Target page is protected by anti-bot verification (e.g., CAPTCHA/Cloudflare challenge). Unable to capture screenshot.",
"protectionDetails": {
"status": 403,
"finalUrl": "https://target-site.example/cdn-cgi/challenge-platform/...",
"indicators": ["verify you are human", "cloudflare ray id"],
"selectors": [".cf-turnstile"]
}
}
}
}

Solution:

  • Verify organization membership
  • For protected target pages, use a URL that does not trigger anti-bot challenges or provide compliant access via allowed headers/proxy

404 Not Found​

Resource Error - Requested resource doesn't exist.

Common Causes:

  • Invalid endpoint
  • Resource ID doesn't exist
  • Resource belongs to different user/organization

Examples:

Invalid Endpoint:

{
"success": false,
"error": {
"code": "ROUTE_NOT_FOUND",
"message": "Route not found"
}
}

Resource Not Found:

{
"success": false,
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Screenshot request not found"
}
}

Solution:

  • Verify endpoint URL is correct
  • Check resource ID exists
  • Ensure resource belongs to your account

409 Conflict​

Conflict Error - Resource conflict (e.g., duplicate entry).

Example:

{
"success": false,
"error": {
"code": "DUPLICATE_ENTRY",
"message": "A record with this information already exists"
}
}

Solution:

  • Check for existing resources
  • Use unique identifiers
  • Update existing resource instead of creating duplicate

429 Too Many Requests​

Rate Limit Error - Rate limit exceeded.

Response Headers:

X-RateLimit-Limit: 40
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1633024800

Example:

{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Screenshot rate limit exceeded, please try again later."
}
}

Solution:

  • Wait for rate limit reset (check X-RateLimit-Reset header)
  • Implement exponential backoff
  • Reduce request frequency
  • Add delays between requests in automation workflows

500 Internal Server Error​

Server Error - Unexpected server error.

Example:

{
"success": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "An internal server error occurred"
}
}

Solution:

  • Retry the request after a delay
  • Check BoltShot status page
  • Contact support if persistent
  • Include request ID in support request

502 Bad Gateway​

Upstream AI Error - External AI provider request failed.

Common Causes:

  • Invalid or expired OpenAI API key
  • OpenAI timeout or temporary outage
  • Upstream provider rejected the image/prompt payload

Example:

{
"success": false,
"error": {
"code": "OPENAI_ANALYSIS_FAILED",
"message": "Screenshot failed",
"details": {
"requestId": "uuid",
"message": "OpenAI analysis timed out after 120000ms"
}
}
}

Solution:

  • Verify your OpenAI API key
  • Full-page or high-resolution screenshots send a large image to the model and often need more than a few seconds; the server default timeout is 120s (OPENAI_TIMEOUT_MS in the API environment)
  • Retry with a shorter/simpler prompt
  • Retry after a short delay if provider is degraded

Validation Errors​

400 Validation Error​

When validation fails, you'll receive detailed error information:

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{
"field": "email",
"message": "Invalid email format",
"value": "invalid-email"
},
{
"field": "password",
"message": "Password must be at least 8 characters",
"value": "short"
}
]
}
}

Common Validation Errors:

Invalid Email:

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation Error",
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
}
}

Invalid URL:

{
"success": false,
"error": {
"code": "MISSING_REQUIRED_FIELD",
"message": "URL is required for screenshot generation."
}
}

Invalid Parameter Type:

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{
"field": "viewportWidth",
"message": "Must be a number",
"value": "invalid"
}
]
}
}

Solution:

  • Review error details for specific field issues
  • Ensure all required fields are provided
  • Verify data types match expected format
  • Check field constraints (min/max values, formats)

Screenshot-Specific Errors​

OpenAI Parameter Pairing Error​

If only one OpenAI field is provided (openaiPrompt without key, or key without prompt), the API returns a validation error.

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
"'openaiApiKey' is required when 'openaiPrompt' is provided. Use X-OpenAI-Api-Key header (recommended) or openaiApiKey query parameter."
]
}
}

Element Not Found​

When using clipSelector, if the element doesn't exist:

{
"success": false,
"error": {
"code": "OPERATION_FAILED",
"message": "Screenshot failed",
"details": {
"requestId": "uuid",
"message": "Element with selector \"#main-content\" not found"
}
}
}

Solution:

  • Verify CSS selector is correct
  • Ensure element exists on the page
  • Check if element loads after page load (use waitForSelector)

Timeout Errors​

If page takes too long to load:

{
"success": false,
"error": {
"code": "OPERATION_FAILED",
"message": "Screenshot failed",
"details": "Navigation timeout of 60000 ms exceeded"
}
}

Solution:

  • Use faster waitUntil option
  • Check if URL is accessible
  • Verify network connectivity

Target Protected by CAPTCHA/Challenge​

If the requested site is behind anti-bot verification (such as reCAPTCHA/hCaptcha/Cloudflare challenge pages), the API returns a 403 with TARGET_PROTECTED:

{
"success": false,
"error": {
"code": "TARGET_PROTECTED",
"message": "Screenshot failed",
"details": {
"requestId": "uuid",
"message": "Target page is protected by anti-bot verification (e.g., CAPTCHA/Cloudflare challenge). Unable to capture screenshot."
}
}
}

Notes:

  • No screenshot is returned when this happens.
  • Credits are only consumed after successful capture, so protected-page failures do not consume credits.

Storage Errors​

If storage upload fails:

{
"success": false,
"error": {
"code": "OPERATION_FAILED",
"message": "Screenshot failed",
"details": "Storage upload failed: Access denied"
}
}

Solution:

  • Verify storage credentials
  • Check storage bucket permissions
  • Test storage connection
  • Review storage configuration

Database Errors​

Sequelize Validation Error​

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Database validation failed",
"details": [
{
"field": "email",
"message": "Email must be unique"
},
{
"field": "organizationName",
"message": "Organization name is required"
}
]
}
}

Solution:

  • Check for duplicate entries
  • Ensure all required fields are provided
  • Verify data constraints

Sequelize Unique Constraint Error​

{
"success": false,
"error": {
"code": "DUPLICATE_ENTRY",
"message": "A record with this information already exists"
}
}

Solution:

  • Check for existing resources
  • Use unique identifiers
  • Update instead of create

Error Handling Best Practices​

1. Always Check Response Status​

const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json();
// Handle error
throw new Error(error.error);
}

2. Implement Retry Logic​

async function requestWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) return await response.json();

// Don't retry client errors (4xx)
if (response.status >= 400 && response.status < 500) {
throw new Error(`Client error: ${response.status}`);
}

// Retry server errors (5xx) and rate limits (429)
if (response.status >= 500 || response.status === 429) {
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
continue;
}

throw new Error(`HTTP ${response.status}`);
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}

3. Handle Rate Limits Gracefully​

if (response.status === 429) {
const resetTime = response.headers.get('X-RateLimit-Reset');
const waitTime = (resetTime * 1000) - Date.now();
await new Promise(resolve => setTimeout(resolve, waitTime));
// Retry request
}

4. Log Errors for Debugging​

try {
const result = await takeScreenshot(options);
} catch (error) {
console.error('Screenshot failed:', {
error: error.message,
requestId: error.requestId,
options: options
});
// Notify or handle error
}

5. Provide User-Friendly Messages​

function getErrorMessage(error) {
switch (error.status) {
case 400:
return 'Invalid request. Please check your parameters.';
case 401:
return 'Authentication failed. Please check your API key.';
case 402:
return 'Insufficient credits. Please upgrade your plan.';
case 429:
return 'Rate limit exceeded. Please try again later.';
case 500:
return 'Server error. Please try again or contact support.';
default:
return 'An unexpected error occurred.';
}
}

Getting Help​

If you encounter an error you can't resolve:

  1. Check Error Details: Review the details field for specific information
  2. Check Request ID: Include requestId in support requests
  3. Review Documentation: Check relevant documentation sections
  4. Contact Support: Email [email protected] with:
    • Error message and details
    • Request ID (if available)
    • Request parameters (sanitized)
    • Steps to reproduce

Next Steps​