Skip to main content

Error Handling

Understanding and handling Browser7 API errors.

Error Response Format

All API errors return a JSON response with an appropriate HTTP status code:

{
"error": "Error Type",
"message": "Human-readable description of what went wrong"
}
FieldTypeDescription
errorstringShort error identifier
messagestringDetailed error message for debugging

HTTP Status Codes

2xx Success

CodeStatusDescription
200OKRequest succeeded
201CreatedResource created successfully

4xx Client Errors

CodeStatusDescription
400Bad RequestInvalid request parameters
401UnauthorizedInvalid or missing API key
402Payment RequiredInsufficient account balance
404Not FoundResource not found
429Too Many RequestsRate limit exceeded

5xx Server Errors

CodeStatusDescription
500Internal Server ErrorUnexpected server error
503Service UnavailableService temporarily unavailable

Common Errors

400 Bad Request

Returned when request parameters are invalid or malformed.

Example Response:

{
"error": "Bad Request",
"message": "Invalid URL: must include protocol (http:// or https://)"
}

Common Causes:

  • Missing required parameters (e.g., url field)
  • Invalid parameter types (e.g., string instead of number)
  • Invalid parameter values (e.g., unsupported country code)
  • Malformed JSON in request body
  • Invalid wait action configuration
  • Too many wait actions (max 10)
  • Invalid wait action timeout values

Solutions:

  • Validate all parameters before sending
  • Check parameter types match the API specification
  • Ensure JSON is properly formatted
  • Review Create Render endpoint documentation

Example:

# Bad - missing protocol
curl -X POST https://api.browser7.com/v1/renders \
-H "Authorization: Bearer b7_your_api_key" \
-H "Content-Type: application/json" \
-d '{"url": "example.com"}'

# Good - includes protocol
curl -X POST https://api.browser7.com/v1/renders \
-H "Authorization: Bearer b7_your_api_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'

401 Unauthorized

Returned when authentication fails.

Example Response:

{
"error": "Unauthorized",
"message": "Invalid or missing API key"
}

Common Causes:

  • API key not included in Authorization header
  • Malformed Authorization header (missing "Bearer " prefix)
  • Invalid API key
  • Typo in API key
  • Using wrong environment's API key

Solutions:

  • Verify your API key in the Dashboard
  • Ensure header format: Authorization: Bearer b7_your_api_key
  • Check for extra spaces or newlines in the API key
  • Use environment variables to avoid typos

Example:

# Bad - missing "Bearer " prefix
curl https://api.browser7.com/v1/renders \
-H "Authorization: b7_your_api_key"

# Good - correct format
curl https://api.browser7.com/v1/renders \
-H "Authorization: Bearer b7_your_api_key"

402 Payment Required

Returned when your account has insufficient balance.

Example Response:

{
"error": "Insufficient Balance",
"message": "Your account balance is insufficient to complete this request"
}

Common Causes:

  • Account balance is $0.00 or less than $0.01
  • Large batch job depleted balance mid-run

Solutions:

  • Check your balance: Dashboard or GET /account/balance
  • Purchase more renders: BillingPurchase Renders
  • Implement balance checks before batch operations

Example:

const client = new Browser7({ apiKey: process.env.BROWSER7_API_KEY });

// Check balance before batch job
const balance = await client.getAccountBalance();
const rendersNeeded = 1000;
const estimatedCost = rendersNeeded * 0.01;

if (balance.totalBalance < estimatedCost) {
throw new Error(`Insufficient balance: need $${estimatedCost}, have $${balance.totalBalance}`);
}

// Proceed with batch job

404 Not Found

Returned when the requested resource doesn't exist.

Example Response:

{
"error": "Not Found",
"message": "Render not found"
}

Common Causes:

  • Invalid render ID
  • Typo in render ID
  • Render ID from a different account
  • Requesting a render that was never created

Solutions:

  • Verify the render ID from the create render response
  • Check for typos or truncated IDs
  • Ensure you're using the correct API key for the account

429 Too Many Requests

Returned when you exceed the rate limit.

Example Response:

{
"error": "Rate Limit Exceeded",
"message": "Too many requests. Please retry after 60 seconds"
}

Common Causes:

  • Sending too many requests too quickly
  • Not respecting rate limits for your plan
  • Aggressive polling without delays

Solutions:

  • Implement exponential backoff
  • Check the Retry-After header for suggested wait time
  • Review Rate Limits documentation
  • Space out batch operations
  • Use the retryAfter field when polling renders

Example:

async function createRenderWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await client.createRender(url, options);
} catch (error) {
if (error.message.includes('429') && i < maxRetries - 1) {
const waitTime = Math.pow(2, i) * 1000; // Exponential backoff
console.log(`Rate limited, waiting ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
} else {
throw error;
}
}
}
}

500 Internal Server Error

Returned when an unexpected server error occurs.

Example Response:

{
"error": "Internal Server Error",
"message": "An unexpected error occurred"
}

Common Causes:

  • Temporary server issue
  • Bug in the API
  • Infrastructure problem

Solutions:

  • Retry the request after a short delay
  • If the error persists, contact support@browser7.com
  • Implement retry logic with exponential backoff

503 Service Unavailable

Returned when the service is temporarily unavailable. The response includes a Retry-After header indicating how many seconds to wait before retrying.

Example Response:

HTTP/1.1 503 Service Unavailable
Retry-After: 2
{
"error": "Service Unavailable",
"message": "Server is at capacity, please retry shortly"
}

Common Causes:

  • Server at capacity (all render slots busy)
  • Scheduled maintenance
  • Infrastructure issues

Solutions:

  • Respect the Retry-After header and retry after the suggested delay
  • The load balancer will automatically route retries to less loaded servers
  • Check status.browser7.com for service status
  • If issue persists, contact support

Render-Specific Errors

When a render job fails after being accepted, the GET /v1/renders/:id response (HTTP 422) includes detailed error and billing information:

{
"status": "failed",
"errorCode": "RENDER_TIMEOUT",
"errorMessage": "Overall render exceeded 120 second timeout",
"billable": true,
"charged": true,
"chargedAmountCents": 1
}

Each error code is classified as either user-caused (billable, $0.01) or system error (not billable, $0.00). System errors are never charged - Browser7 does not charge for its own infrastructure failures.

See the Error Codes Reference for the complete list of error codes, their billing classification, and recommended fixes.

Error Handling in SDKs

All Browser7 SDKs provide typed error classes that map directly to HTTP status codes, eliminating the need to parse error message strings.

Node.js

import Browser7, { AuthenticationError, RateLimitError, InsufficientBalanceError, RenderError } from 'browser7';

const client = new Browser7({ apiKey: process.env.BROWSER7_API_KEY });

try {
const result = await client.render('https://example.com');
console.log(result.html);
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Authentication failed - check your API key');
} else if (error instanceof InsufficientBalanceError) {
console.error('Insufficient balance - purchase more renders');
} else if (error instanceof RateLimitError) {
console.error('Rate limited - slow down requests');
} else if (error instanceof RenderError) {
console.error(`Render failed: ${error.errorCode}`);
} else {
console.error('Error:', error.message);
}
}

Python

from browser7 import Browser7, AuthenticationError, RateLimitError, InsufficientBalanceError, RenderError

client = Browser7(api_key=os.environ['BROWSER7_API_KEY'])

try:
result = client.render('https://example.com')
print(result.html)
except AuthenticationError:
print('Authentication failed - check your API key')
except InsufficientBalanceError:
print('Insufficient balance - purchase more renders')
except RateLimitError:
print('Rate limited - slow down requests')
except RenderError as e:
print(f'Render failed: {e.error_code}')
except Exception as e:
print(f'Error: {e}')

PHP

use Browser7\Browser7Client;
use Browser7\AuthenticationError;
use Browser7\RateLimitError;
use Browser7\InsufficientBalanceError;
use Browser7\RenderError;

$client = new Browser7Client($_ENV['BROWSER7_API_KEY']);

try {
$result = $client->render('https://example.com');
echo $result->html;
} catch (AuthenticationError $e) {
echo 'Authentication failed - check your API key';
} catch (InsufficientBalanceError $e) {
echo 'Insufficient balance - purchase more renders';
} catch (RateLimitError $e) {
echo 'Rate limited - slow down requests';
} catch (RenderError $e) {
echo 'Render failed: ' . $e->getErrorCode();
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}

Best Practices

1. Always Handle Errors

Never assume requests will succeed. Implement proper error handling for all API calls.

2. Log Errors for Debugging

Log full error responses including status codes and messages:

console.error(`API Error [${statusCode}]: ${error.message}`);

3. Implement Retry Logic

Retry transient errors (500, 503) with exponential backoff:

import { Browser7Error } from 'browser7';

async function retryWithBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
const isRetryable = error.statusCode >= 500 || error.statusCode === 429;

if (isRetryable && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}

4. Validate Before Sending

Validate parameters client-side before making API calls:

function validateRenderOptions(url, options = {}) {
if (!url || !url.startsWith('http')) {
throw new Error('URL must start with http:// or https://');
}

if (options.waitFor && options.waitFor.length > 10) {
throw new Error('Maximum 10 wait actions allowed');
}

// More validation...
}

5. Monitor Error Rates

Track error rates to identify issues early:

let errorCount = 0;
let requestCount = 0;

async function monitoredRender(url) {
requestCount++;
try {
return await client.render(url);
} catch (error) {
errorCount++;
const errorRate = (errorCount / requestCount) * 100;

if (errorRate > 10) {
console.warn(`High error rate: ${errorRate.toFixed(2)}%`);
}

throw error;
}
}

Getting Help

If you encounter persistent errors:

  1. Check the API Status Page
  2. Review this documentation and related endpoint docs
  3. Search for similar issues in the community
  4. Contact support@browser7.com with:
    • Your API key (last 4 characters only)
    • Request and response details
    • Timestamp of the error
    • Steps to reproduce