Rate limit

X sent a rate-limit header, or error code 88.

The error#

When x-rate-limit-remaining is 0 and x-rate-limit-reset is greater than 0, the client logs Rate limited: {status - remaining/limit - username - errors} and raises HandledError after closing the context until x-rate-limit-reset.

When the error list contains a string that starts with (88) Rate limit exceeded and the remaining header is still above 0, it logs Ban detected: and closes the account with inactive=True. The same HandledError is raised. The comment in the source says this is how a ban is inferred, because there is no direct ban flag.

HandledError is raised with no message. The useful text is the log line.

What triggers it#

A GraphQL response carried those headers or that error prefix. HandledError tells the retry loop to try another account rather than return the body.

How to confirm#

Search the log for Rate limited: or for (88) Rate limit exceeded. inactive=True on the 88 path means that account will not be picked again until you clear it. The header path waits until the reset time and keeps the account.

Fixes#

The pool's response is to rotate accounts. One account that is reset-limited comes back after x-rate-limit-reset. An account marked inactive on code 88 stays out. Adding accounts raises the ceiling. It does not change the per-account headers. NoAccountError is what you get when every account is in one of these states.

SocialScrape#

Profile is GET /v1/twitter/profile. One post is GET /v1/twitter/tweet. A profile's posts are GET /v1/twitter/profile/tweets. These read what X shows logged out.

Failed requests cost 0 credits. New accounts get 100 credits on signup, no card. Suspended accounts come back as removed, unknown ones as not_found.

Questions

Is HandledError the message I should match?

The class is empty. Match the log text Rate limited: or (88) Rate limit exceeded.

What is SocialScrape's own limit?

rate_limited, with a retry-after header. It costs 0 credits.