Skip to content

Rate Limiting

Every route carries a per-client limit, enforced by SlowAPI and keyed on the client IP.

Client identification

The limiter keys on the client IP, taken from X-Forwarded-For only when the request arrives from an address listed in FORWARDED_ALLOW_IPS.

A wildcard is rejected at startup

If any caller's forwarded headers were trusted, every limit could be bypassed by rotating a header value. FORWARDED_ALLOW_IPS=* is refused rather than accepted — set your proxy's address or CIDR. The default is 127.0.0.1,::1.

Configuring it wrongly is not a silent problem either: every request then appears to come from the proxy, so all clients share one bucket and the first busy user locks out everyone else. See Reverse Proxy.

Limits by route

Authentication

Route Limit
GET /login 20/minute
POST /login 5/minute
POST /logout 20/minute

The login limit is the backstop behind the invisible anti-bot check.

Jobs

Route Limit
POST /api/submit 10/minute
GET /api/jobs 60/minute
GET /api/jobs/{id} 60/minute
POST /api/jobs/{id}/cancel 30/minute
POST /api/jobs/{id}/retry 10/minute
POST /api/jobs/remove-all 2/minute

Media

Route Limit
GET /job/{id} 120/minute
GET /download/{id} 30/minute
GET /audio-source/{id} 60/minute
GET /thumbnail/{id} 120/minute
GET /api/thumbnail-cache/{key} 120/minute
GET /api/thumbnail/resolve 30/minute
GET /api/thumbnail-proxy 30/minute

Settings and system

Route Limit
GET /api/settings 60/minute
POST /api/settings 5/minute
GET /api/stats 30/minute
POST /api/stats/reset 5/minute
GET /api/stats/bpm-clusters 30/minute
GET /api/updates 30/minute
GET /api/system/host 60/minute
GET /api/info 20/minute

Events

Route Limit
GET /events 30/minute
GET /api/jobs/{id}/events 30/minute

Independently of the rate limit, at most 200 concurrent SSE connections are accepted, with a 32-event queue per client. A client that cannot keep up is disconnected rather than allowed to grow its queue without bound.

Cookies

Route Limit
GET /api/cookies 30/minute
POST /api/cookies/{platform} 10/minute
POST /api/cookies/{platform}/paste 10/minute
DELETE /api/cookies/{platform} 10/minute

Trimming

Route Limit
POST /api/trim/{id} 10/minute
DELETE /api/trim/{id} 30/minute
GET /api/trim/{id}/{trim_id}/download 30/minute

Lalal.ai

Route Limit
GET /api/lalal/status 30/minute
POST /api/lalal/auth/activation-key 5/minute
POST /api/lalal/auth/logout 10/minute
POST /api/lalal/{job_id} 5/minute
GET /api/lalal/download/{job_id} 10/minute
Route Limit
POST /api/share/{job_id} 20/minute
GET /share/{token} 20/minute

The redeem limit is a security control

Share tokens are 8 characters (48 bits). Brute force is bounded by this limit rather than by token length, so raising it materially weakens share links.

Exceeding a limit

The response is 429 Too Many Requests. The UI surfaces it as a toast; API clients should back off and retry.

Tuning

The limits are compiled into the route decorators and are not configurable at runtime — they encode a security posture rather than a capacity setting. If a limit genuinely blocks a legitimate workflow, open an issue rather than working around it with a proxy rule; the numbers reflect what each route costs and what abuse of it would achieve.

What it does not cover

Rate limiting bounds request frequency, not resource consumption. A single accepted download can still occupy a worker for an hour. Concurrency and memory are governed separately — see Resources & Workers.