Crawlzodocs
Guides

Rate limits and throughput

What the API tells you about your limits, and how to size a job.

The headers

Every response carries the current limit state.

HeaderMeaning
X-RateLimit-LimitThe size of your burst allowance.
X-RateLimit-RemainingHow much of it is left right now.
X-RateLimit-ResetMilliseconds until enough allowance has returned for the request that was refused. 0 when nothing is being refused.
Retry-AfterOn a 429, how long to wait before trying again.

Read these rather than hardcoding a rate. Limits are set per account and can be raised, so a number you compile in today will be wrong the day your plan changes.

When you get a 429, wait for Retry-After and try again. RATE_LIMITED and QUOTA_EXCEEDED are not billed, so backing off correctly costs you nothing.

The limit is a burst allowance, not a fixed window

Your allowance refills continuously rather than resetting on a clock. Every request takes one unit, and units come back at a steady rate, so the allowance is full again shortly after you stop.

The practical effect is that X-RateLimit-Remaining only falls when you send requests faster than they refill. Spacing calls a second or two apart will show a full allowance on every response, because it refilled between them. Sending twenty-five at once visibly draws it down.

This is what you want for this kind of API. A burst of parallel calls is exactly how you page through a feed or fan out across a list of profiles, and the allowance is sized for that rather than forcing you to trickle requests.

Sizing a job

Latency, not rate limiting, is usually what governs throughput. These endpoints read live pages, so a call takes seconds.

Measured across every endpoint on its documented example request:

Time
Fastest0.7s
Median3.7s
90th percentile12.3s
95th percentile21.7s
Slowest29.8s

Sixteen endpoints answer in under two seconds, and seven take more than twenty. Each endpoint page shows its own measured time.

The practical consequence is that concurrency, not request rate, sets your throughput. Thirty concurrent workers at a four second median gives you roughly 450 calls a minute. Getting there with one worker in a loop would take four hours.

Running a large job

Set a client timeout of at least 120 seconds. A timeout shorter than the work turns a slow success into a failure, and you pay for the call either way.

Run calls concurrently with a bounded pool. A fixed pool of workers pulling from a queue gives you predictable throughput and a single place to add backoff.

Make the unit of work a single call, and record request_id against it. When something needs investigating later, that id is what we search on.

Checkpoint your cursors. If a long paging job dies at page 40, you want to resume rather than restart, which matters most on the endpoints where paging is the expensive part.

On this page