Docs
Errors

Errors

TwittrAPI status codes, error bodies, which errors are charged and refunded, and which ones to retry.

Errors come back as JSON with an error string:

{ "error": "Invalid tweet ID" }

Some errors add fields: errorInfo (X's raw reply, for example on /username/to/id), errorCode, or a stable code string (for example on proxy errors). Do not parse the message text; it can change. Use the status code and, where present, code.

Status codes

"Charged" means the call costs one call's price. "Refunded" means it was charged and the amount was put back right away; the response then has the header X-Refunded: true. "Not charged" means the request was rejected before billing.

StatusWhenBilling
200Success.Charged
400A required parameter is missing or malformed (for example no listId, or more than 500 IDs), or X answered with an error the API could not classify.Refunded
401Missing or unknown API key.Not charged
402No balance left, or the trial expired.Not charged
403Key deactivated, or the endpoint is not in your plan.Not charged
403X refused the request for this region.Charged
404X says the user, tweet or other object does not exist, or the path does not exist.Charged
407Account actions only: your proxy rejected the credentials, could not be reached, timed out or refused the connection to X. See Proxy errors.Refunded
408The request took longer than 60 seconds.Refunded
409The request failed with 400 on every automatic retry (see below).Refunded
422A parameter has an invalid value (non-numeric ID, bad username, unsupported search operator) or X rejected the input.Charged
429Rate limit for your key exceeded. See Rate limits.Not charged
500, 502, 503, 504Something failed on our side or at X. 502 also covers a search that got only empty pages from X after several retries. 504: X did not answer in time.Refunded
X's statusAccount actions pass X's own HTTP status through (for example 401 or 403 when X rejects the session).Charged unless it is 400, 407, 408 or 5xx

Endpoint pages list the validation errors of each endpoint under "Errors".

Proxy errors (407)

Account actions (/client/*, /premium/*) go out through the proxy you send. When that proxy fails, the request never reaches X and you get 407 with a code:

{ "error": "Your proxy rejected the credentials (407)", "code": "PROXY_AUTH_FAILED" }
codeMeaningWhat to do
PROXY_AUTH_FAILEDThe proxy refused the username or password (it answered 407, or SOCKS5 authentication failed).Check the credentials in the proxy URL and that this IP is allowed by your proxy provider.
PROXY_UNREACHABLENo connection to the proxy (refused, unknown host).Check host and port; is the proxy online?
PROXY_TIMEOUTConnecting through the proxy timed out (message Proxy connection timed out).Retry, or use a faster proxy.
PROXY_TUNNEL_FAILEDThe proxy accepted the connection but would not open a tunnel to X (for example 502 or 403 from the proxy).Check your proxy provider's target or country restrictions.
PROXY_INVALIDThe proxy value is not a valid proxy URL (422 instead of 407).Use the form http://user:pass@host:port.

Proxy errors are refunded at once, because nothing reached X, and they do not count as API errors on the status page. An invalid proxy URL (422) is charged like other input errors.

Automatic retries

A request that fails with 400 or a connection error is retried automatically. If every attempt fails, you get 409 (after 400s) or 502 / 503 (connection errors), all refunded. A response that needed a retry has the header X-Retried: true. You are billed once per request. Account actions (/client/*, /premium/*) are never retried, because the action may already have happened on X.

What to retry

StatusRetry?
408, 409, 429, 500, 502, 503, 504Yes, with exponential backoff (for example 0.5 s, 1 s, 2 s, up to a few tries).
400Once at most. If it repeats, check the parameters.
401, 402, 403, 404, 422No. Fix the key, balance or input first.
Account actionsOnly after checking on X that the action did not happen.

Temporary failures carry code and retryable in the body, and Retry-After when you can retry:

{"error": "Temporarily unavailable. You were not charged, please retry in a few seconds.", "code": "service_restarting", "retryable": true}
CodeStatusMeaningWhat to do
service_restarting503Briefly unavailable on our side.Retry after Retry-After.
x_unavailable503X is briefly not reachable.Retry after Retry-After.
upstream_timeout504No answer in time.Retry.
result_unknown502The connection broke during an account action. It may have gone through.Check on X first.

The official SDKs retry 429, 5xx and network errors with backoff by default, and raise typed errors (for example NotFoundError, RateLimitError, InsufficientBalanceError in Python).

from twittrapi import TwittrAPI, InsufficientBalanceError, NotFoundError, TwittrAPIError
 
client = TwittrAPI()
try:
    user = client.users.get_by_username("someone")
except NotFoundError:
    print("No such user")
except InsufficientBalanceError:
    print("Top up your balance")
except TwittrAPIError as exc:
    print(f"API error {exc}")

Empty results are not errors

X often answers with 200 and an empty timeline instead of an error: for example for likes, which X made private. /user/by/username/{username} answers 200 with {"data": {}, "userExists": false} for a handle that does not exist.