API GuidesAugust 1, 202610 min readingMarcel Czuryszkiewicz

Social Media API Rate Limits: Every Platform Compared

Meta derives your allowance from engagement, YouTube charges weighted units, Bluesky counts points, and X charges money. A single counter will be wrong on most of them. The reference table, the four counting models behind it, and how to build a limiter that survives all four.

Social Media API Rate Limits: Every Platform Compared

Social media API rate limits are not one thing. Meta derives your allowance from how much engagement an account gets, YouTube charges weighted units per method, Bluesky counts points per write, Mastodon counts plain requests per window, and X charges money per call. A single counter across platforms will be wrong on at least three of them. This is the reference table, the four counting models behind it, and how to build a limiter that survives all of them.

The reference table

Verified against official documentation. Where a figure is not published, that is stated rather than guessed.

PlatformLimitWindowScoped to
Facebook Pages4800 × engaged users24 hApp, via Page or system user token
Facebook (app token)200 × users1 hApp
Instagram4800 × impressions24 hApp–user pair
Threads4800 × impressions, minimum 10 impressions24 hApp–user pair
YouTube10,000 units (cost-weighted)Day, resets midnight PacificProject
Bluesky (writes)5,000 points/h, 35,000 points/dayRollingAccount (DID)
Bluesky (API)3,000 requests5 minIP
Mastodon300 requests5 minAccount and IP, separately
Mastodon (media)30 uploads30 minAccount
DiscordPer-route buckets + a global limitVariesBot, route, and top-level resource
TikTokQPS caps at app, endpoint and advertiser levelPer secondApp / advertiser
X2M post reads/month cap; billed per callMonthAccount
LinkedInNot published-App and member
PinterestPublished per-endpoint; e.g. 5,000 calls/min per ad account on some endpointsMinuteAd account

Two entries deserve a warning label.

Instagram's publishing cap is a moving number. Rather than hardcoding it, query it:

curl -G "https://graph.facebook.com/v26.0/${IG_USER_ID}/content_publishing_limit" \
  -d "access_token=${TOKEN}"

Meta ships an endpoint specifically so you do not have to guess - and the reason is that Meta's own documentation contradicts itself. On a single page of the Content Publishing guide, one section states accounts are limited to 100 API-published posts in a rolling 24-hour period, while another states 50. The content_publishing_limit endpoint returns the number that is actually enforced for that account.

So every blog post quoting a fixed publishing cap is quoting a snapshot of a figure the platform's own docs disagree on. Query it. The container flow this cap applies to, and what it does to a fleet of connected accounts, is covered in our Instagram Graph API guide.

Discord tells you explicitly not to hardcode anything. Their documentation states that limits depend on many factors and are subject to change, and that apps should parse response headers instead. Take them at their word.

Four counting models

Once you see the models, the table stops looking arbitrary.

1. Requests per window

The obvious one. N requests per T minutes. Mastodon (300 per 5 minutes), Bluesky's PDS layer (3,000 per 5 minutes per IP), Pinterest per endpoint.

Easy to reason about, easy to implement, and the only model most generic "API rate limiting" articles describe.

2. Cost-weighted quota

YouTube gives a project 10,000 units per day, but methods cost different amounts. videos.insert costs 1,600 units - so a naive reading of "10,000 per day" suggests plenty of headroom, while the reality is about six uploads.

Two multipliers people miss: paginated responses cost the quota per page, not per logical query, and Live Streaming API methods draw from the same pool.

Bluesky uses the same idea with different units: writes cost points - CREATE 3, UPDATE 2, DELETE 1 - against 5,000 points per hour. That works out to roughly 1,666 record creations per hour.

3. Derived from engagement

This is Meta's model, and it is the one that breaks people's mental models entirely.

Facebook Pages:  4800 × engaged users  per 24 h
Instagram:       4800 × impressions    per 24 h
Threads:         4800 × impressions    per 24 h  (minimum 10 impressions)

Your allowance is a function of how popular the account is, not of what you pay or which tier you are on.

The consequence is counter-intuitive and operationally painful: a brand-new account has almost no budget. Exactly when your onboarding wants to backfill a content calendar for a new client, the limit is at its tightest. A large account you have barely touched, meanwhile, has enormous headroom.

Threads at least sets a floor - impressions are treated as a minimum of 10 - so a brand-new Threads account gets 48,000 calls rather than zero. Facebook Pages and Instagram have no such floor documented.

Capacity planning per customer, not per app, is the only thing that works here. And you cannot compute it in advance: you have to observe it. The header mechanics behind this model, and the two time fields that throttle you before the call count does, are in our Facebook Graph API guide.

4. Money

X's pay-per-use model has no calls-per-hour limit in the traditional sense. You are billed per operation, with a 2 million post-read monthly cap on pay-per-use. The limiter is your budget, and the failure mode is not a 429 - it is an invoice.

That changes what your throttle is protecting. Everywhere else you are protecting availability; on X you are protecting spend. Our breakdown of the numbers is in X (Twitter) API pricing.

The Meta limit increases with commitment: new account ≈ zero budget, large account ≈ huge. It shows why onboarding hurts the most

Response headers, side by side

Reading headers is how you stay under a limit instead of discovering it. Every platform does it differently.

PlatformHeadersWhat they carry
Meta (FB/IG/Threads)X-App-UsageJSON: call_count, total_time, total_cputime - each a percentage, 0–100
Meta AdsX-Ad-Account-Usageacc_id_util_pct, reset_time_duration, ads_api_access_tier
DiscordX-RateLimit-Limit, -Remaining, -Reset, -Reset-After, -Bucket, -Global, -ScopeCounts and a bucket ID
MastodonX-RateLimit-Limit, -Remaining, -ResetCounts; reflects the limit you are closest to exceeding
BlueskyStandard draft rate-limit headersCounts
X / LinkedIn / TikTok / PinterestVary by endpointRely on 429 and documented per-endpoint limits

Three practical notes that cost real time.

Meta's header is percentages, not counts. call_count: 28 means you have used 28% of your allowance, not that you have made 28 calls. Teams that treat it as a count discover the mistake at 100.

The two time fields matter as much as the call count. You can sit at call_count: 12 and still be throttled because total_cputime reached 100 - which is what happens when you request wide field sets over large edges. Trimming requested fields is the fix, and it is not a micro-optimisation.

Discord's X-RateLimit-Bucket is the real key. Several endpoints can share one bucket, and the same endpoint with different top-level resources (channel_id, guild_id, webhook_id) can have independent limits. Keying your counter on the URL path gives you the wrong answer in both directions. Key it on the bucket.

Mastodon returns overlapping limits. An endpoint can be subject to several at once; the headers describe whichever you are nearest to breaching. So the numbers you see can jump between limits without your traffic changing shape.

Publishing limits are separate

Request limits and publishing limits are different ceilings, and hitting the second one is more visible to your customers.

PlatformPublishing constraint
InstagramA documented per-24 h cap - query content_publishing_limit rather than assuming
MastodonMedia uploads: 30 per 30 minutes. Deletes and un-reblogs: 30 per 30 minutes
BlueskyWrites cost points; ~1,666 creations per hour
YouTubevideos.insert at 1,600 units means roughly six uploads per day on default quota
TikTokPer-second QPS at app, endpoint and advertiser level

A scheduler that respects request limits and ignores these will pass every load test and then fail on a customer's launch day, when twelve posts go out in one hour.

fifteen models, one limiter. We built it - you can just use it

Building one limiter over four models

You cannot normalise these into a single counter. What you can normalise is the decision: may I make this call now?

Model each platform as a budget with its own unit. Requests, units, points, percent, or dollars. The limiter's interface is canSpend(platform, account, cost); the unit lives inside the implementation.

Track per account, not per app. Meta's engagement-derived model makes app-level counters meaningless - two customers on the same app have completely different ceilings. Your key is (platform, account).

Trust headers over your own arithmetic. Your counter drifts: retries, parallel workers, calls from other parts of your system. The header is the platform's own view. Where one exists, reconcile to it after every response and treat your local count as an optimistic estimate between calls.

after each response:
  if platform exposes usage headers:
      budget[account] = parse(headers)        # authoritative
  else:
      budget[account] -= cost(request)        # estimate

Back off with jitter, and respect Retry-After when given. Discord returns retry_after in seconds as a float - use it rather than your own guess. Exponential backoff without jitter turns one throttled worker into a synchronised thundering herd.

Classify errors before retrying. A 429 is retryable. A permission error is not, and retrying it burns budget to produce the same failure. This is the most common way teams turn a small problem into an outage - the retry-classification section of our social media API integration guide covers the policy in full.

Queue with per-account fairness. One customer backfilling 500 posts should not starve everyone else. Round-robin across accounts rather than draining a global FIFO.

What this costs you to maintain

Every number in the table above has changed at least once in the last two years. Meta changed Instagram's publishing cap. X replaced tiers with pay-per-use. Versioned APIs sunset on rolling schedules.

A rate limiter is not a build-once component. It is a surface that needs watching, and the watching is the expensive part.

bundle.social runs one limiter across every platform we support, tracks per-account budgets, reconciles against platform headers, and queues with per-account fairness. When a platform changes its maths, we change ours. Your integration keeps calling one endpoint.

FAQ

Why is my Instagram rate limit lower than another account's? Meta derives the allowance from impressions: 4800 × impressions per 24 hours. A lower-reach account gets a smaller budget. It is a property of the account, not your app tier.

What does call_count mean in Meta's X-App-Usage header? It is the percentage of your allowance consumed, 0–100 - not a count of calls. Throttling begins at 100, and the same applies to total_time and total_cputime.

How many videos can I upload to YouTube per day? The default project quota is 10,000 units per day and videos.insert costs 1,600, so roughly six uploads before other calls are considered. Quota resets at midnight Pacific.

Do batched requests use less quota? Generally no. On Meta's Graph API each call inside a batch counts separately for both call limits and CPU limits. Batching reduces round trips, not consumption. Field expansion genuinely reduces call count.

Should I hardcode rate limits from documentation? No. Discord's docs say so explicitly, and every other platform has changed its numbers. Read response headers where they exist, query live endpoints like Instagram's content_publishing_limit, and treat 429 as authoritative.