Glossary

Converting the Bluesky API Rate Limit Into Posts Per Hour

Taras Shynkarenko
Taras Shynkarenko
Updated: 8 min read
Converting the Bluesky API Rate Limit Into Posts Per HourConverting the Bluesky API Rate Limit Into Posts Per Hour

TL;DR, Quick Answer

8 min read

Bluesky meters record writes in points, not requests. Each account gets 5,000 points per hour and 35,000 per day, where a CREATE costs 3 points, an UPDATE 2 and a DELETE 1. That is 1,666 posts per hour, 11,666 per day, and 486 per hour if you want to run all day without stalling. A separate 3,000 requests per five minutes applies per IP, and login attempts are capped far lower than either.

What is the Bluesky API rate limit?

Every Bluesky API rate limit that governs writing is denominated in points rather than requests: a Bluesky PDS gives each account 5,000 points per hour and 35,000 points per day, and a CREATE costs 3 points, an UPDATE 2 points and a DELETE 1 point. Requests that cross a limit receive an HTTP 429 response.

Almost every other social API counts calls. Bluesky counts the record operations inside those calls, sums them per account (per DID, not per app password or per token), and applies the point budget on top of a separate HTTP request budget. The official rate limits page says so directly: "These limits are on top of any related HTTP API requests."

The point costs, straight from the docs:

Action typeValue
CREATE3 points
UPDATE2 points
DELETE1 point

The docs convert that into records for exactly one case, likes, and stop. The rest of the arithmetic is below.

How many posts per hour can one Bluesky account make?

One account can create 1,666 records per hour and 11,666 records per day, and a Bluesky post is one record. Divide the budget by the cost:

OperationPoints eachPer hour (5,000 pts)Per day (35,000 pts)
CREATE (post, like, repost, follow)31,66611,666
UPDATE (putRecord)22,50017,500
DELETE (unlike, unfollow, remove post)15,00035,000

The CREATE numbers round down and strand two points each hour, since 5,000 divided by 3 is 1,666.67 and 35,000 divided by 3 is 11,666.67. The docs quote 1,666 and 11,666, which matches.

Batching does not help with points. A single com.atproto.repo.applyWrites call can carry many record writes, and the docs are explicit that the limits "sum up all of those individual record writes." What batching helps with is the request budget, covered further down.

A post, a like, a repost and a follow all cost the same 3 points. The record collections are app.bsky.feed.post, app.bsky.feed.like, app.bsky.feed.repost and app.bsky.graph.follow, and the budget does not distinguish between them, so a follow bot and a posting bot draw from one pot.

Why is the daily limit only seven hours of the hourly limit?

The daily ceiling of 35,000 points is exactly seven times the hourly ceiling of 5,000, so seven hours at full burst exhausts the entire day. The docs page never says this, and it is the most useful thing to know before you write a scheduler.

If the hourly ceiling were the only constraint, a day would allow 5,000 times 24, or 120,000 points. The daily cap is 29 percent of that. The hourly ceiling is a burst allowance; the daily ceiling is the real budget.

The sustainable rate is what matters for anything that runs continuously:

WindowPointsCREATEs
Burst, one hour5,0001,666
Sustained, per hour across 24h1,458486
Sustained, per minute248

That last line is the number to design around. 11,666 creates across 1,440 minutes is 8.1 per minute, one write every 7.4 seconds. A worker faster than that is borrowing from later in the day; a worker at the hourly ceiling is out of budget by hour eight.

What does a thread, an edit or a deleted post actually cost?

A thread costs 3 points per post in it, because each post in a thread is its own record. Nothing about the reply structure is free. Here is the arithmetic for the write patterns people actually run:

PatternPointsPer hourPer day
One post31,66611,666
Five post thread153332,333
Post, then edit (createRecord plus putRecord)51,0007,000
Post, then delete41,2508,750
Like, then unlike41,2508,750

Images and video change the request count, not the point count. Uploading a blob through com.atproto.repo.uploadBlob is not a record write, so it costs zero points: a post with four images is five HTTP requests and 3 points. Blob size caps and the 300 grapheme cap on post text are separate subjects, and neither touches the write budget.

A phone displaying an error message, illustrating what happens when an app hits a rate limit.

AdaptlyPost
AdaptlyPost

Start 7-Day FREE Trial

All-platform analytics

Social Inbox

AI-powered assistant

Which limit hits first, the point budget or the request budget?

For a single account the point budget hits first, and for a fleet of accounts sharing one IP the request budget hits first. Bluesky applies both at once: 3,000 requests per five minutes measured per IP, across all endpoints, and the point budget measured per account.

Convert the request limit to the same units. 3,000 per five minutes is 600 per minute and 36,000 per hour. One account writing flat out manages 1,666 creates per hour, a twentieth of the IP allowance, so a solo bot never sees the IP limit.

Now put several accounts behind one IP. Spread evenly, one account at its hourly ceiling makes 1,666 divided by 12, or 138.8 write requests per five minute window. Divide 3,000 by 138.8 and you get 21.6. Twenty-one accounts fit under the IP ceiling at 2,915 requests; the twenty-second crosses it at 3,054. That crossover is published nowhere, and it is why multi-account automation from one server behaves differently from the same code on one account. The docs do not say how the two budgets interact when they collide, only that both exist.

A person typing a login form on a laptop, tied to the section on account login limits.

What are the login limits, and why do they bite before the write limits?

com.atproto.server.createSession is capped at 30 per 5 minutes and 300 per day per account, which is 39 times stricter than the write budget it gates. An automation that logs in fresh for every post has a real ceiling of 300 posts per day, not 11,666, because 11,666 divided by 300 is 38.9.

The full set of account and identity limits from the docs:

EndpointMeasured perLimit
Overall API requestsIP3,000 per 5 minutes
com.atproto.identity.updateHandleaccount10 per 5 minutes, 50 per day
com.atproto.server.createAccountIP100 per 5 minutes
com.atproto.server.createSessionaccount30 per 5 minutes, 300 per day
com.atproto.server.deleteAccountIP50 per 5 minutes
com.atproto.server.resetPasswordIP50 per 5 minutes

Failed logins are metered separately and much harder, and the docs do not mention this at all. On 10 September 2026, a com.atproto.server.createSession request to bsky.social with invalid credentials returned:

HTTP/2 401
ratelimit-limit: 10
ratelimit-remaining: 9
ratelimit-policy: 10;w=86400

{"error":"AuthenticationRequired","message":"Invalid identifier or password"}

Two more failed attempts dropped ratelimit-remaining to 8 and then 7, so the counter is live. A window of 86,400 seconds is 24 hours: ten wrong passwords a day, against a documented createSession allowance of 300. Burn ten attempts debugging an app password and you are locked out of that endpoint until the reset timestamp, with no page on the docs site to explain why.

The docs also publish no limit for com.atproto.server.refreshSession, the endpoint a well behaved client should hit instead of createSession. Store the refresh token, refresh the session, and the 300 per day ceiling stops being your constraint.

Working around the login ceiling
1
Call createSession once. It counts against 30 per 5 minutes and 300 per day.
2
Store the refresh token. Keep it instead of the password.
3
Call refreshSession to renew. Skip logging in again.
4
The 300 per day ceiling stops applying. refreshSession carries no documented limit.
createSession burns through its daily allowance fast. refreshSession carries no published limit.

Which rate limit headers does Bluesky actually send?

Bluesky PDS responses carry four headers: ratelimit-limit, ratelimit-remaining, ratelimit-reset and ratelimit-policy. The rate limits page never names them, saying only that "Many HTTP API services return rate limit headers on responses. Developers can use those to debug and understand the current limits, or even automate request throughput and backoff." The atproto XRPC specification names one header, Retry-After, and only as an optional companion to a 429.

Here is a live response. A com.atproto.server.describeServer call to bsky.social on 10 September 2026 returned:

HTTP/2 200
ratelimit-limit: 3000
ratelimit-remaining: 2999
ratelimit-reset: 1789052966
ratelimit-policy: 3000;w=300

ratelimit-policy: 3000;w=300 is the documented 3,000 per 5 minutes written as a limit and a window in seconds, which confirms the published number from the server itself. ratelimit-reset is a Unix timestamp, not a number of seconds to wait, so back off until that moment rather than sleeping for its value.

The same check against public.api.bsky.app returned no ratelimit- headers at all, consistent with the docs calling those endpoints "generous" without publishing a number. The point budget does not appear in any header either, since it is not tied to a single endpoint. You have to count it yourself.

Do these limits apply to every Bluesky account?

They apply to accounts hosted on Bluesky-operated PDS instances. The docs are careful about this: "Bluesky is built on top of an open network (atproto), and other providers in the network are likely to have different rate-limits." A self-hosted PDS sets its own numbers, and the Bluesky relay applies a separate ceiling to federating servers, at 50 repository stream events per second, 2,600 per hour and 21,000 per day.

The docs close with "All of the limits described here are likely to evolve over time. Hopefully upwards!" Treat every number here as a reading taken on 10 September 2026, and read the headers at runtime rather than hardcoding the constants. Note also that docs.bsky.app now issues a 301 to bsky.network with the path preserved, so the current address for the page quoted throughout is https://bsky.network/docs/rate-limits.

AdaptlyPost
AdaptlyPost

Start 7-Day FREE Trial

All-platform analytics

Social Inbox

AI-powered assistant

What does this mean if you schedule Bluesky posts through a tool?

Scheduling tools sit under the same budget as any other client, because the limits belong to Bluesky and to the account. A queue of scheduled posts spends 3 points per post from the same 35,000 per day that your manual likes and follows draw on. What a scheduler changes is the shape of the spend: posts placed on a calendar go out spaced apart rather than in a burst, which keeps you under the sustained rate instead of the hourly one. AdaptlyPost handles Bluesky post scheduling alongside bulk scheduling and a content calendar, and reads back performance through Bluesky analytics. Publishing the same item to several networks through multi-account posting still costs 3 points on the Bluesky side, once, because it is one record.

Frequently Asked Questions

How many posts can a Bluesky account make per day?

11,666 posts per day, from a 35,000 point daily budget at 3 points per CREATE. Sustained evenly across 24 hours that is 486 posts per hour, or one every 7.4 seconds. The hourly ceiling of 1,666 posts is a burst allowance, and hitting it seven times exhausts the day.

Does a like count against the same Bluesky rate limit as a post?

Yes. A like creates an app.bsky.feed.like record, which is a CREATE worth 3 points, the same as a post. Posts, likes, reposts and follows all draw from one 5,000 point hourly budget per account.

What HTTP status does Bluesky return when you exceed a rate limit?

HTTP 429, described by the docs as "Too Many Requests." The atproto XRPC specification says a 429 response "may be a Retry-After header indicating a specific back-off time period." On PDS endpoints, check ratelimit-reset for the Unix timestamp when the window clears.

Why does my Bluesky login fail after only a few wrong passwords?

Failed com.atproto.server.createSession calls to bsky.social return ratelimit-policy: 10;w=86400, which is 10 attempts per 24 hours, with the error body {"error":"AuthenticationRequired","message":"Invalid identifier or password"}. That limit is not listed on the rate limits page. The documented 30 per 5 minutes and 300 per day apply to successful sessions.

Does batching writes with applyWrites save rate limit budget?

It saves HTTP requests, not points. The docs state that com.atproto.repo.applyWrites "can write to many records in a single API call" and that the limits "sum up all of those individual record writes." Twenty-five creates in one call cost 75 points and one request.

Do Bluesky rate limits apply to self-hosted PDS servers?

The published numbers apply to Bluesky-operated PDS instances. Other providers on atproto set their own, in the docs' words "likely to have different rate-limits." The Bluesky relay does apply its own ceiling to any federating PDS, at 50 repository stream events per second, 2,600 per hour and 21,000 per day, plus 100 accounts maximum and 5 created per second by default.

How many Bluesky accounts can share one IP before hitting the request limit?

Twenty-one accounts writing flat out from behind one IP fit under the 3,000-requests-per-five-minutes ceiling, at 2,915 requests. A twenty-second account crosses it, at 3,054. That crossover only shows up when several accounts share a server, since one account alone uses 139 of the 3,000 requests.

Does uploading images or video eat into the point budget?

Uploading a blob through com.atproto.repo.uploadBlob costs zero points, since it is not a record write. A post with four images spends 3 points for the post record and adds four extra HTTP requests, one per image, five requests total. Point budget only tracks CREATE, UPDATE and DELETE on records, not blob uploads.

What does the ratelimit-reset header actually tell you?

ratelimit-reset is a Unix timestamp marking when the current window clears, not a number of seconds to wait. A com.atproto.server.describeServer response on 10 September 2026 returned ratelimit-reset: 1789052966 alongside ratelimit-limit: 3000 and ratelimit-remaining: 2999. Back off until that moment arrives rather than sleeping for the raw number, and note the atproto spec's Retry-After header is a separate, optional field sent only alongside a 429.

How often can I change my Bluesky handle without hitting a rate limit?

com.atproto.identity.updateHandle is capped at 10 changes per 5 minutes and 50 per day, per account. That is far tighter than the 300-per-day createSession ceiling, so a script that renames handles on a schedule will hit this limit long before it touches its write budget.

Was This Article Helpful?

Let us know what you think!

See us more often in Google

One click marks AdaptlyPost as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.

Before you go...

AdaptlyPost

AdaptlyPost

Schedule your content across all platforms

Manage all your social media accounts in one place with AdaptlyPost.

All-platform analytics

Social Inbox

AI-powered assistant

Related Glossary Terms

Related Articles