API
Handling Polymarket API rate limits in Python
Rate limits are a budget, and a data pipeline that ignores them fails at the worst moment. The API publishes per-minute and per-day limits per plan, exposes usage through get_usage, and tells you how long to wait on a 429.
What this guide covers
- Starter: 60 requests/min, 1,000/day; Pro: 300/min, 50,000/day; Scale: 1,000/min, 200,000/day
- History window also scales with plan: 3 days, 31 days, 90 days
- get_usage returns the plan, limits and current quota usage
- A 429 raises RateLimitError with retry_after in seconds
Know your budget
Each plan meters requests per minute and per day, and the history window scales too - three days on Starter, 31 on Pro, 90 on Scale. Within a minute the burst limit binds; across a day the daily quota binds on long crawls.
Call get_usage at the start of a job to read the plan and current usage. Scheduling a crawl without checking your remaining headroom is how a run ends half-finished at a 429.
| Plan | Per minute | Per day | History |
|---|---|---|---|
| Starter | 60 | 1,000 | 3 days |
| Pro | 300 | 50,000 | 31 days |
| Scale | 1,000 | 200,000 | 90 days |
Budgeting a crawl
Estimate the calls a job needs before running it. Paging a market's books costs one call per page; fetching a hundred markets costs a hundred calls plus pages. If the estimate exceeds your daily quota, narrow the window, reduce the resolution, or spread the crawl across days.
The cheapest lever is resolution. Pulling one-second books over a long window costs many more pages than the same window at one-minute resolution. Choose the coarsest resolution that answers the question.
Reacting to a 429
When you exceed a limit the API returns a rate-limit error and the SDK raises RateLimitError, whose retry_after tells you how many seconds to wait. Sleep that long, then retry the call once. Repeating a 429 without waiting only deepens the problem.
Combine this with local caching so once data is fetched it is never re-fetched. Caching and budgeting together mean the quota is spent on genuinely new data, not on repeats.
Estimating a job before running it
Before a crawl, estimate its cost: pages per market times markets, plus discovery calls. Compare that to your remaining daily quota from get_usage, and if it exceeds the budget, narrow the window or coarsen the resolution.
Record the estimate and the actual usage after the run. The gap tells you how good your model is, and after a few runs you can predict a crawl’s cost well enough to schedule it against your quota rather than discovering the limit mid-run.
Treat the daily quota as the binding constraint for big jobs and the per-minute limit as the constraint for a short burst. Different fixes apply: spread a big job across days, and slow a burst with concurrency limits.
Code examples
import os
import time
from polyorderbooks import PolyOrderbooksClient, RateLimitError
with PolyOrderbooksClient(api_key=os.environ["POLYORDERBOOKS_API_KEY"]) as c:
usage = c.get_usage()
print("plan:", usage["plan"], "limits:", usage["limits"])
slug = "doge-updown-5m-1787486400"
pages = 0
for page in c.iter_market_books(
slug,
start_ts="2026-10-17T07:00:00Z",
end_ts="2026-10-17T08:00:00Z",
resolution="60s",
limit=500,
):
try:
pages += 1
# ... process page['data'] ...
except RateLimitError as err:
time.sleep(err.retry_after or 1)
print("pages fetched:", pages)Free tier
The Starter plan is free, includes order books, prices, and metrics at 250ms resolution, with 3 days of history, 60 requests/min, 1,000/day, 1 free AI backtest, and 3 strategy backtests. No credit card required.
Paid data windows from $19/mo extend history to 30–120 days at higher throughput. Backtest AI add-on is +$19/mo or standalone at $29/mo.
FAQ
What are the plan limits?
Starter: 60 requests/min and 1,000/day with 3 days of history. Pro: 300/min and 50,000/day with 31 days. Scale: 1,000/min and 200,000/day with 90 days.
How do I check my remaining quota?
Call get_usage, which returns the plan, the limits, and current quota usage for your API key.
What should I do on a 429?
Read RateLimitError.retry_after, sleep that many seconds, then retry once. Do not retry immediately, which compounds the limit.
How do I spend less quota?
Cache responses locally so you never re-fetch, and choose the coarsest resolution that answers your question - one-second books cost far more pages than one-minute.