Rate Limits and Usage
How Tabstack's per-minute request rate limits work, what the 429 response carries, and where to see your usage and quota.
Two different things get confused here, so keep them apart. Rate limits are requests per minute: exceed them and you get a 429. Usage is dollars and credits you have consumed: a billing concern you read on a different surface, with nothing to do with the 429. If you are being rate-limited, you do not need to look at your spend.
Rate limits
Section titled “Rate limits”Rate limits are per account. Not per key, not per endpoint. Every key on the account draws from the same per-minute budget, and every endpoint counts against it.
| Plan | Requests per minute |
|---|---|
| Trial | 10 |
| Individual | 10 |
| Team | 25 |
| Pro | 100 |
Read the headers, never hit the wall
Section titled “Read the headers, never hit the wall”Every response carries rate limit headers, not just 429s. This is the part to build around: read your remaining budget off any successful call and slow down before you run out.
| Header | Meaning |
|---|---|
X-RateLimit-Limit | The ceiling for the current window |
X-RateLimit-Remaining | Requests left in the current window |
X-RateLimit-Reset | When the window resets |
A successful response looks like this:
HTTP/1.1 200 OKX-RateLimit-Limit: 100X-RateLimit-Remaining: 87X-RateLimit-Reset: 1717459200Content-Type: application/jsonWhen you exceed the limit
Section titled “When you exceed the limit”You get a 429 with the standard error shape, a single error field. See the Error Reference for the full shape. The 429 also carries a Retry-After header telling you how many seconds to wait:
HTTP/1.1 429 Too Many RequestsRetry-After: 12Content-Type: application/json
{ "error": "rate limit exceeded" }The SDKs retry 429 automatically with exponential backoff, honoring Retry-After, so most developers using an SDK never handle this by hand. See Production Reliability for the retry and backoff behavior.
Handling example
Section titled “Handling example”The better pattern is proactive: read X-RateLimit-Remaining from a normal response and back off before you reach zero. The reactive fallback is to catch the 429 and read Retry-After.
import Tabstack, { RateLimitError } from "@tabstack/sdk";
const client = new Tabstack();
// Proactive: back off early using the headers on a successful call.const { data, response } = await client.extract .json({ url: "https://example.com", json_schema: { type: "object", properties: { title: { type: "string" } } }, }) .withResponse();
const remaining = Number(response.headers.get("X-RateLimit-Remaining"));if (remaining < 5) { console.warn(`Low on budget: ${remaining} requests left this window`); // slow down: reduce concurrency or pause before you hit zero}
// Reactive fallback: catch the 429 and honor Retry-After.try { await client.extract.json({ url: "https://example.com", json_schema: { type: "object", properties: { title: { type: "string" } } }, });} catch (err) { if (err instanceof RateLimitError) { const retryAfter = err.headers?.get("Retry-After"); console.warn(`Rate limited. Retry after ${retryAfter}s`); } else { throw err; }}from tabstack import Tabstack, RateLimitError
client = Tabstack()
# Proactive: back off early using the headers on a successful call.response = client.extract.with_raw_response.json( url="https://example.com", json_schema={"type": "object", "properties": {"title": {"type": "string"}}},)
remaining = int(response.headers.get("X-RateLimit-Remaining"))if remaining < 5: print(f"Low on budget: {remaining} requests left this window") # slow down: reduce concurrency or pause before you hit zero
data = response.parse()
# Reactive fallback: catch the 429 and honor Retry-After.try: client.extract.json( url="https://example.com", json_schema={"type": "object", "properties": {"title": {"type": "string"}}}, )except RateLimitError as err: retry_after = err.response.headers.get("Retry-After") print(f"Rate limited. Retry after {retry_after}s")Usage and quota
Section titled “Usage and quota”Different surface, different units. Usage is what you have spent, measured in dollars and credits, and you read it in the console, not from a response header.
There is no rate-limit visibility in the console. The console shows usage, not your per-minute request budget. Your account’s rate limit is listed on your billing page, and your remaining budget for the current window is in the response headers above.
What the console shows depends on your plan:
- Individual: pay-as-you-go, billed per 1k credits; current usage shows as dollar spend.
- Team and Pro: credits used against credits included (500k on Team, 3M on Pro). If you go over your allocation, the console also shows the dollar amount you are over.
For the rate limit that applies to your plan, see your billing page. For spend and quota, go to the console. For a rate limit increase, contact support.