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

# Errors

> HTTP status codes returned by twitterapi.io, what they mean, and how your code should react.

## Status codes

| Code | Meaning | What to do |
| - | - | - |
| `200` | Success. Check the body's `status` field too: some endpoints return `"status": "error"` with a `msg` (for example `user not found`) and HTTP 200. | Handle `status == "error"` as a normal "no result" case. |
| `400` | A required parameter is missing or invalid. Body: `{"detail": "userName is required"}` | Fix the request; retrying the same request won't help. |
| `401` | The API key is invalid. Body: `{"error": "Unauthorized", "message": "API key is invalid"}` | Copy the key again from your [dashboard](https://twitterapi.io/dashboard). |
| `402` | Your account is out of credits. Body: `{"error": "Unauthorized", "message": "Credits is not enough.Please recharge"}` | **Stop retrying** and top up on your dashboard. Retrying won't succeed until you add credits. |
| `403` | No API key was sent. Body: `{"error": "Forbidden", "message": "API key required. Please include x-api-key in your request header..."}` | Add the `x-api-key` header (see [Authentication](/authentication)). |
| `404` | The path doesn't exist. | Check the endpoint path in the API reference. |
| `429` | Too many requests per second for your account. Body: `{"error": "Too Many Requests", "message": "Too Many Requests.your qps is 20 requests per second."}` | Slow down and retry with backoff. See [Rate limits](/rate-limits). |
| `500` / `502` / `503` | A temporary problem on our side or upstream. | Retry with exponential backoff (for example 1 s, 2 s, 4 s). |

## Invalid search queries

Some search queries can never return results, because X rejects them. Advanced search, bulk search and tweet filter rules return `400` with an explanation for these, and you are not charged:

| Problem | Example | Fix |
| - | - | - |
| Unclosed double quote | `silicon anode" battery` | Every quoted phrase needs an opening and a closing `"`. |
| Unbalanced parentheses | `(from:a OR from:b` | Every `(` needs a matching `)`. Parentheses inside a quoted phrase are fine. |
| `retweets_of:` operator | `from:a OR retweets_of:a` | X no longer supports it. To see who retweeted a tweet, use [Get Tweet Retweeters](/api-reference/endpoint/get_tweet_retweeter). For tweets an account itself retweeted, use `from:username filter:nativeretweets`. |
| `list:` combined with `OR` | `list:123 OR list:456` | `list:` must be used on its own at the top level. Send one query per list. |

In bulk search, only the invalid query gets an `error` field and empty results; the other queries in the batch run normally.

## Recommended retry logic

* **Retry**: `429`, `500`, `502`, `503`, network timeouts. Use exponential backoff and a limit, for example up to 5 attempts.
* **Don't retry**: `400`, `401`, `402`, `403`, `404`. These need a code or account change first.
* A `402` loop is the most common mistake we see: a script keeps retrying after its credits run out. Check for `402` and stop.

<CodeGroup>
  ```python Python theme={null}
  import time, requests

  def call(url, params, key, attempts=5):
      for i in range(attempts):
          r = requests.get(url, params=params, headers={"x-api-key": key}, timeout=30)
          if r.status_code in (429, 500, 502, 503):
              time.sleep(2 ** i)
              continue
          if r.status_code == 402:
              raise RuntimeError("Out of credits: top up at https://twitterapi.io/dashboard")
          r.raise_for_status()
          return r.json()
      raise RuntimeError("Gave up after retries")
  ```
</CodeGroup>

Still stuck? Email [hello@twitterapi.io](mailto:hello@twitterapi.io) with the request URL and the time (UTC), and we'll look it up.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.