> ## Documentation Index
> Fetch the complete documentation index at: https://docs.surfsky.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> Read API error responses, choose a retry policy, and diagnose request or browser failures.

Most API errors use this shape:

```json theme={null}
{
  "success": false,
  "msg": "Maximum parallel browsers",
  "data": null,
  "code": "parallel_browsers_limit_reached"
}
```

Use the HTTP status and `code`, when present, to choose an action. Keep `msg` for logs and diagnostics. `data` may contain validation details or information from the browser.

Some forwarded browser responses and scraping errors do not include `code`, and may use `detail` or `error` instead. Your error handler should tolerate these shapes and non-JSON responses from a network intermediary. Record the status and `x-cloud-tracing-uuid` header when available.

## Retrying

Choose retries by the reported condition rather than the HTTP status alone:

| Condition                                                                        | Action                                                                                      |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `cluster_is_full`, temporary startup or provider failure, `503`                  | Retry with bounded exponential backoff and jitter. Stop after a limited number of attempts. |
| `rate_limits_reached`                                                            | Wait and reduce the request rate. Either the minute or hour window may be exhausted.        |
| `parallel_browsers_limit_reached`                                                | Wait for a slot or stop a session your job owns.                                            |
| Traffic quota exhausted                                                          | Check the allowance and reset time; repeated immediate retries will not help.               |
| Invalid credentials, missing resource, invalid body, unavailable account feature | Correct the request or account configuration first.                                         |
| `profile_is_running`                                                             | Stop the profile before editing, deleting, or importing cookies.                            |
| `profile_version_conflict`                                                       | Re-read the profile, reconcile the intended change, then retry.                             |

A `400 cluster_is_full` can be retried; a `429` caused by exhausted traffic quota needs a different response. HTTP status alone cannot distinguish these cases.

If a start request times out or loses its connection, its outcome is uncertain. Check [active sessions](/sessions#find-running-sessions) before repeating it. Creating a profile or one-time session is not an idempotent operation, so an automatic retry can create an extra resource.

## Request errors

| Status | Code                              | What it means                                                                                                                                  |
| ------ | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | `proxy_required`                  | The browser has no way out to the internet. Pass `proxy`, `open_vpn`, or `wireguard`, or use a plan with a pool.                               |
| 400    | `cluster_is_full`                 | No capacity right now. Retry with backoff.                                                                                                     |
| 400    | `profile_start_failed`            | The browser did not come up. Retry with backoff; if it repeats, inspect the response details and the proxy configuration.                      |
| 400    | `profiles_limit_reached`          | Your plan's persistent profile limit. Delete unused profiles.                                                                                  |
| 400    | `persistent_profiles_not_allowed` | Your plan is one-time only.                                                                                                                    |
| 400    | `proxy_pool_unavailable`          | No pool is attached to your account. Bring your own proxy.                                                                                     |
| 400    | `shared_pool_country_unavailable` | The shared pool has nothing in that country at the moment. Pick another, or use premium.                                                       |
| 400    | `proxy_provider_error`            | The upstream proxy provider failed. Retry.                                                                                                     |
| 400    | `chromedriver_not_enabled`        | Start the profile with `enable_chromedriver: true` before talking to the ChromeDriver endpoint.                                                |
| 400    | `scrape_timeout`                  | `/scrape` gave up after 120 seconds. Usually the page never satisfied your wait condition.                                                     |
| 400    | `extension_limit_reached`         | 100 extensions per account.                                                                                                                    |
| 400    | `no_file_provided`                | The extension upload had no file part.                                                                                                         |
| 400    | `user_is_blocked`                 | The account is blocked. Contact support.                                                                                                       |
| 401    | `not_authorized`                  | Missing or wrong `X-Cloud-Api-Token`.                                                                                                          |
| 403    | `subscription_is_expired`         | No active subscription.                                                                                                                        |
| 403    | `namespace_not_allowed`           | Your account is served by a dedicated host and you called the shared one. Use the host you were given.                                         |
| 403    | `premium_pool_unavailable`        | Premium proxies are not enabled for your account.                                                                                              |
| 403    | `shared_pool_unavailable`         | Shared proxies are not enabled for your account.                                                                                               |
| 403    | `region_not_chosen`               | Pick a region in the dashboard before starting browsers.                                                                                       |
| 403    | `region_managed`                  | Your plan's region is assigned by support, not self-serve.                                                                                     |
| 404    | `profile_not_found`               | No such profile, or it belongs to another account. The API does not distinguish the two.                                                       |
| 404    | `extension_not_found`             | No such extension.                                                                                                                             |
| 404    | `plan_not_exists`                 | No such plan.                                                                                                                                  |
| 404    | `premium_quota_not_applicable`    | This plan bills premium traffic per GB and has no quota to report.                                                                             |
| 409    | `profile_is_running`              | You tried to edit or delete a profile that is up. Stop it first.                                                                               |
| 409    | `browsers_still_running`          | The operation needs every browser stopped.                                                                                                     |
| 500    | `extension_upload_failed`         | Upload to storage failed. Retry.                                                                                                               |
| 500    | `extension_delete_failed`         | Delete from storage failed. Retry.                                                                                                             |
| 500    | `proxy_locations_unavailable`     | The proxy provider's location list could not be fetched.                                                                                       |
| 502    | `unexpected_browser_response`     | The browser answered with something that was not JSON. Check whether the session is still active, then inspect or stop it before replacing it. |
| 503    | `service_unavailable`             | Temporary. Retry with backoff.                                                                                                                 |

## Limit errors

All of these are `429`. Responses to profile calls carry your current window in headers - see [Limits](/limits).

| Code                              | What it means                                                                                                                  |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `rate_limits_reached`             | Requests per minute or per hour exceeded. Wait for the window.                                                                 |
| `parallel_browsers_limit_reached` | You already have as many browsers running as your plan allows. Stop one, or check `GET /users/browser-limits` before starting. |
| `shared_traffic_limit_reached`    | Shared proxy traffic allowance exhausted. Switch to your own proxy or to premium.                                              |
| `premium_traffic_limit_reached`   | Premium proxy quota exhausted. Top up or use your own proxy.                                                                   |
| `region_change_too_soon`          | Regions cannot be changed again this soon.                                                                                     |

## Errors from the browser

These come from the pod running your browser rather than the API gateway, so you will usually see them on start, on `/scrape`, or on a cookie call.

| Status | Code                       | What it means                                                                                                      |
| ------ | -------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| 400    | `bad_proxy`                | The proxy did not accept the connection, or failed to route. Check credentials and that the endpoint is reachable. |
| 400    | `invalid_fingerprint`      | The browser rejected the fingerprint. Check its fields against the fingerprint reference.                          |
| 400    | `cookies_not_found`        | The profile has no stored cookies to export.                                                                       |
| 400    | `cookies_disabled`         | The profile's storage options have cookies turned off.                                                             |
| 400    | `pod_is_acquired`          | The session is already in use.                                                                                     |
| 409    | `profile_version_conflict` | The profile changed between the read and the write. Re-read it and retry.                                          |
| 422    | `validation_error`         | Malformed request body. `data` lists the fields.                                                                   |
| 500    | `browser_failed_to_start`  | The browser process died during startup. `data` carries what it printed.                                           |
| 503    | `app_outdated`             | The browser image is being updated. Retry shortly.                                                                 |
| 503    | `tunnel_not_ready`         | The proxy tunnel did not come up in time. Retry.                                                                   |

## Validation errors

Gateway validation errors return `422 validation_error` with the failing fields in `data`. For example:

```json theme={null}
{
  "success": false,
  "msg": "Validation error",
  "code": "validation_error",
  "data": [
    {
      "loc": ["body", "fingerprint", "os"],
      "msg": "Input should be 'win', 'mac' or 'android'",
      "type": "enum"
    }
  ]
}
```
