Platform
Error Handling
Understanding Banata API error responses, error codes, and how to handle them in your application.
The Banata API uses standard HTTP status codes and returns structured JSON error responses. This page covers all error types you may encounter and how to handle them.
Error Response Format
All error responses follow this structure:
{
"error": "Human-readable error message",
"code": "MACHINE_READABLE_CODE",
"requiredPlan": "pro",
"currentPlan": "free"
}The error field is always present. The code, requiredPlan, and currentPlan fields are included when relevant.
HTTP Status Codes
400 — Bad Request
Your request body or query parameters contain invalid data.
{ "error": "Invalid weight: 'ultra'. Must be one of: light, medium, heavy" }Common causes:
- Invalid enum value for
weight,isolation,egressProfile,runtime, orsize - Invalid
maxDurationMs(must be positive number) - Invalid
region(must be 3 lowercase letters) - Proxy/egress configuration mismatch
- Missing required fields
401 — Unauthorized
The API key is missing, invalid, expired, or revoked.
{ "error": "Invalid or missing API key" }Check that:
- The
Authorizationheader is present:Authorization: Bearer br_live_... - The key is not revoked or expired
- The key belongs to the correct organization
403 — Forbidden
Your API key lacks the required permission, or the feature is not available on your plan.
Plan feature not available:
{
"error": "Stealth mode is not available on the Free plan. Upgrade to Builder or higher to enable anti-detection.",
"code": "PLAN_FEATURE_UNAVAILABLE",
"requiredPlan": "builder",
"currentPlan": "free"
}Plan limit exceeded:
{
"error": "maxDurationMs (3600000) exceeds your plan limit of 30 minutes. Current plan: pro",
"code": "PLAN_LIMIT_EXCEEDED"
}Permission denied:
{
"error": "Insufficient permissions",
"code": "PERMISSION_DENIED"
}404 — Not Found
The requested session does not exist.
{ "error": "Session not found" }{ "error": "Sandbox session not found" }409 — Conflict
The session is in an invalid state for the requested operation.
{ "error": "Sandbox is not ready (state: queued)" }{ "error": "Sandbox has no assigned machine" }This usually means you are trying to execute commands or access files before the sandbox is fully started. Poll the session status until it reaches ready before sending exec/code/fs requests.
429 — Too Many Requests
You have hit a rate limit or usage cap.
Rate limit:
{ "error": "Rate limit exceeded. Please try again later." }The response includes a Retry-After header with the number of seconds to wait.
Concurrent session limit:
{ "error": "Concurrent browser session limit reached" }Monthly quota:
{ "error": "Monthly browser hours limit reached" }502 — Bad Gateway
The request was proxied to a worker but the worker did not respond correctly.
{ "error": "Failed to execute command" }This can happen with sandbox exec/code requests if the sandbox worker is unreachable. Retry the request.
503 — Service Unavailable
Scheduling failed — no machine could be assigned to your session.
{
"error": "Failed to schedule sandbox",
"code": "SCHEDULING_FAILED",
"sessionId": "...",
"reason": "No available machines in the requested region"
}This is usually transient. Retry after a short delay.
Error Codes Reference
| Code | Status | Description |
|---|---|---|
PLAN_FEATURE_UNAVAILABLE | 403 | Feature requires a higher plan. Check requiredPlan field. |
PLAN_LIMIT_EXCEEDED | 403 | Value exceeds your plan's maximum (e.g., maxDurationMs). |
PERMISSION_DENIED | 403 | API key does not have the required permission scope. |
SCHEDULING_FAILED | 503 | No machine could be assigned. Includes reason for debugging. |
Handling Errors in Code
With the SDK
import { BrowserCloud, BanataError } from "@banata-boxes/sdk";
const cloud = new BrowserCloud({ apiKey: "br_live_..." });
try {
const { cdpUrl, close } = await cloud.launch({
stealth: true,
recording: true,
});
// ... use the session
} catch (error) {
if (error instanceof BanataError) {
switch (error.code) {
case "PLAN_FEATURE_UNAVAILABLE":
console.log(`Upgrade to ${error.requiredPlan} to use this feature`);
break;
case "PLAN_LIMIT_EXCEEDED":
console.log("Reduce maxDurationMs or upgrade your plan");
break;
default:
console.log(`Error ${error.status}: ${error.message}`);
}
}
}With raw HTTP
const response = await fetch("https://api.boxes.banata.dev/v1/browsers", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ stealth: true }),
});
if (!response.ok) {
const error = await response.json();
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") || "5", 10);
// Wait retryAfter seconds, then retry
}
if (error.code === "PLAN_FEATURE_UNAVAILABLE") {
// Suggest upgrade to error.requiredPlan
}
throw new Error(error.error);
}Best Practices
-
Always check the status code before parsing the response body. A 201 is a successful creation; anything else is an error.
-
Handle 429 with backoff. Rate limits protect both you and other users. The
Retry-Afterheader tells you exactly how long to wait. -
Check for
PLAN_FEATURE_UNAVAILABLEbefore retrying. This error won't resolve with retries — you need to either remove the feature flag or upgrade your plan. -
Retry 5xx errors. These are almost always transient. Use exponential backoff.
-
Wait for
readystate before executing. Sending exec/code/fs requests to a sandbox inqueuedorassigningstate returns 409. Poll first.
Next Steps
- API Reference — Full endpoint documentation
- Rate Limits — Rate limit values per endpoint
- Billing & Plans — Plan limits and feature availability