Skip to content
yeetpostyeetpost

Mastodon API rate limits

Mastodon API rate limits: 300 requests per 5 minutes per account and per IP, 30 media uploads per 30 minutes, the X-RateLimit headers and a sender that stays under them.

4 min read

Mastodon publishes its API rate limits as a short table, and the numbers are small enough that a posting job can hit them without doing anything unusual. The limits apply per Mastodon account and per IP address, and every server runs its own copy of them, so a job that posts to accounts on five instances is dealing with five separate sets of counters.

The documented limits

Mastodon's rate limit documentation lists these defaults:

ScopeEndpointLimit
Per accountAll endpoints and methods300 requests per 5 minutes
Per accountPOST /api/v1/media30 requests per 30 minutes
Per accountDELETE /api/v1/statuses/:id and POST /api/v1/statuses/:id/unreblog30 requests per 30 minutes
Per IPAll endpoints and methods300 requests per 5 minutes
Per IPPOST /api/v1/accounts5 requests per 30 minutes

Two rows matter for posting. The general limit of 300 requests per 5 minutes is generous for text, but it counts every call, including the reads a client makes to check a status or fetch the timeline. The media limit is the one that bites: 30 uploads per 30 minutes per account, and a status with four images spends four of them before the status itself is created. Seven four-image posts in half an hour exhausts the budget.

The delete limit has the same shape. A cleanup script that removes old statuses can delete 30 every 30 minutes, which turns a purge of a few thousand posts into a job that runs for days.

These values are the defaults in Mastodon's code. Servers running forks or modified configurations can differ, so treat the table as the starting point and the response headers as the truth for a given server.

The headers

Mastodon returns the limit state on responses, so a sender can see a limit coming before it hits it:

  • X-RateLimit-Limit, the number of requests allowed in the window.
  • X-RateLimit-Remaining, how many are left.
  • X-RateLimit-Reset, the timestamp at which the window resets.

When a request falls under several limits at once, for example a media upload that counts toward both the general limit and the media limit, the headers report the one you are closest to exceeding. That makes the headers safe to use as the single input for a limiter: read X-RateLimit-Remaining, and when it reaches zero, wait until X-RateLimit-Reset.

Requests over the limit get an HTTP 429 response. Retrying immediately only produces more 429s; wait until the reset time from the last response you received.

Per account, per IP and per server

The per-IP limit is the one people forget. A service that posts for many users from one server shares a single 300-per-5-minutes budget per Mastodon instance across all of them, regardless of how many accounts it holds tokens for. Fifty users on mastodon.social posting through the same worker draw from the same per-IP counter on mastodon.social. Users on other instances do not, because each instance counts on its own.

So the key for a local limiter is the instance host plus the account for account limits, and the instance host plus your outgoing IP for IP limits.

A sender that stays under them

post(instance, account, status):
    for image in status.images:
        wait_for(instance, account, "media")     # 30 per 30 min
        res = POST https://{instance}/api/v2/media  image
        update(instance, account, res.headers)
    wait_for(instance, account, "all")           # 300 per 5 min
    res = POST https://{instance}/api/v1/statuses  status
          headers: Idempotency-Key: {status.id}
    if res.status == 429:
        sleep_until(res.headers["X-RateLimit-Reset"])
        retry with the same Idempotency-Key
    update(instance, account, res.headers)

The Idempotency-Key header is worth sending on every status creation. Mastodon uses it to recognise a repeated submission, so a retry after a timeout does not publish the same status twice. Rate limits and timeouts tend to arrive together during busy periods, and a duplicate post is a more visible failure than a delayed one.

For a scheduled burst, such as a release announcement going out to several accounts at once, upload media first and spread the uploads out, then create the statuses. That keeps the slow, tightly limited step away from the moment the posts are meant to appear.

The shorter route

yeetpost posts to Mastodon with one HTTP call to /api/v2/post/mastodon with an API key. It works on any instance, checks the text against that instance's own character limit, and handles image uploads and threads. The Mastodon posting API page covers what it supports, and scheduled posts let you queue a status for a set time.

Keep reading

All posts

Post from your code today

Two accounts are free and need no credit card. Your first post can go to the sandbox connection, which takes it and publishes nothing.