{"id":1712,"library":"slowapi","title":"SlowAPI: Rate Limiting for Starlette & FastAPI","description":"SlowAPI is a Python library that provides a flexible rate-limiting extension for Starlette and FastAPI applications. It builds upon the 'limits' library to offer various storage backends (in-memory, Redis, Memcached) and granular control over rate limits per route or globally. The current version is 0.1.9, and it is actively maintained with an irregular release cadence.","status":"active","version":"0.1.9","language":"en","source_language":"en","source_url":"https://github.com/laurents/slowapi","tags":["fastapi","starlette","rate-limiting","middleware","security"],"install":[{"cmd":"pip install slowapi","lang":"bash","label":"Basic Installation"},{"cmd":"pip install 'slowapi[redis]' # For Redis backend\npip install 'slowapi[memcached]' # For Memcached backend","lang":"bash","label":"With Storage Backends"}],"dependencies":[{"reason":"Core web framework dependency for ASGI applications.","package":"starlette"},{"reason":"Core rate-limiting logic provider, SlowAPI is an extension for ASGI.","package":"limits"},{"reason":"Optional: For FastAPI application integration and its dependency injection system.","package":"fastapi","optional":true},{"reason":"Optional: Required for using Redis as a rate-limiting storage backend.","package":"redis","optional":true},{"reason":"Optional: Required for using Memcached as a rate-limiting storage backend.","package":"python-memcached","optional":true}],"imports":[{"symbol":"Limiter","correct":"from slowapi import Limiter"},{"note":"Moved to `slowapi.util` in recent versions for clarity.","wrong":"from slowapi.extension import get_ipaddr","symbol":"get_ipaddr","correct":"from slowapi.util import get_ipaddr"},{"note":"The exception class is located in `slowapi.errors`, not `slowapi.exceptions`.","wrong":"from slowapi.exceptions import RateLimitExceeded","symbol":"RateLimitExceeded","correct":"from slowapi.errors import RateLimitExceeded"},{"symbol":"_rate_limit_exceeded_handler","correct":"from slowapi import _rate_limit_exceeded_handler"}],"quickstart":{"code":"import uvicorn\nfrom fastapi import FastAPI, Request\nfrom slowapi import Limiter, _rate_limit_exceeded_handler\nfrom slowapi.util import get_ipaddr\nfrom slowapi.errors import RateLimitExceeded\n\n# Initialize Limiter with a key function and default limits\n# Using in-memory storage for simplicity, but can be 'redis://localhost:6379' etc.\nlimiter = Limiter(key_func=get_ipaddr, default_limits=[\"5/minute\", \"100/day\"])\napp = FastAPI()\napp.state.limiter = limiter # Essential for decorator-based limits\n\n# Register the exception handler to return a 429 response\napp.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)\n\n@app.get(\"/unlimited\")\nasync def read_unlimited():\n    return {\"message\": \"This endpoint is not rate limited.\"}\n\n@app.get(\"/\")\n@limiter.limit(\"10/minute\") # Route-specific limit\nasync def read_root(request: Request):\n    # The 'request' argument is required by the key_func (get_ipaddr)\n    return {\"message\": \"Hello, rate-limited world!\"}\n\n@app.get(\"/fast/\")\n@limiter.limit(\"2/second\", \"/fast/\") # Another route with a custom scope\nasync def read_fast(request: Request):\n    return {\"message\": \"Too fast, too furious!\"}\n\n# To run this application:\n# 1. Save the code as 'main.py'\n# 2. Run from your terminal: uvicorn main:app --reload --port 8000","lang":"python","description":"This quickstart demonstrates how to integrate SlowAPI with a FastAPI application. It sets up a global `Limiter` instance using the client's IP address (`get_ipaddr`) for identification and registers an exception handler for `RateLimitExceeded` errors. Two endpoints are defined, one with a 10 requests/minute limit and another with a 2 requests/second limit, showcasing both global and route-specific rate limiting."},"warnings":[{"fix":"Place `app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)` and ensure `app.state.limiter` is set *before* other middlewares if using the middleware approach, or be mindful of the order in `app.add_middleware()`.","message":"Middleware order is critical. If your application uses other middlewares (e.g., authentication, proxy headers) that modify the `Request` object (e.g., setting `request.client.host`), ensure that `slowapi`'s middleware is added *after* them. This guarantees the `key_func` receives the final, correct request state for identification.","severity":"gotcha","affected_versions":"0.1.0+"},{"fix":"Always provide a `key_func` during `Limiter` initialization. For custom identification (e.g., by user ID), define a function that extracts the ID from the `Request` object (e.g., `request.state.user.id`).","message":"The `key_func` (e.g., `get_ipaddr`) is essential for identifying unique requests for rate limiting. Misconfiguring or omitting it will lead to all requests sharing the same limit or ineffective rate limiting. Custom `key_func`s must correctly extract a unique identifier from the `Request` object.","severity":"gotcha","affected_versions":"0.1.0+"},{"fix":"Add `app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)` to your FastAPI/Starlette application setup.","message":"To return a custom HTTP 429 (Too Many Requests) response when a rate limit is exceeded, you must explicitly register the `_rate_limit_exceeded_handler` (or a custom handler) with your application's exception handlers. Failing to do so will result in a generic server error (e.g., HTTP 500) instead of the expected 429.","severity":"gotcha","affected_versions":"0.1.0+"},{"fix":"Ensure `storage_uri` is correctly set, e.g., `memory://` for testing, `redis://localhost:6379` for Redis, or `memcached://localhost:11211` for Memcached. Install the necessary optional dependencies (e.g., `slowapi[redis]`) for non-memory backends.","message":"The rate-limiting storage backend is determined by the `LIMITS_STORAGE_URI` environment variable or the `storage_uri` parameter in `Limiter`. Not setting it or setting it incorrectly (e.g., forgetting `memory://` for in-memory or incorrect Redis/Memcached URIs) will lead to runtime errors or incorrect rate limiting behavior.","severity":"gotcha","affected_versions":"0.1.0+"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}