{"id":5457,"library":"requests-ratelimiter","title":"Requests Ratelimiter","description":"Requests-Ratelimiter is a Python library that provides easy-to-use rate-limiting capabilities for the popular `requests` library. It acts as a wrapper around `pyrate-limiter`, implementing the leaky bucket algorithm to control the rate of HTTP requests. It is currently at version 0.9.3 and generally follows the release cadence of its underlying `pyrate-limiter` dependency, with updates typically driven by new features or fixes in the core rate-limiting logic.","status":"active","version":"0.9.3","language":"en","source_language":"en","source_url":"https://github.com/JWCook/requests-ratelimiter","tags":["requests","rate-limiting","api-client","http","pyrate-limiter"],"install":[{"cmd":"pip install requests-ratelimiter","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core HTTP library that requests-ratelimiter extends.","package":"requests","optional":false},{"reason":"Underlying rate-limiting logic.","package":"pyrate-limiter","optional":false},{"reason":"Commonly used with requests-ratelimiter for caching responses. The order of mixins matters.","package":"requests-cache","optional":true},{"reason":"Required for Redis persistent backend for rate limits.","package":"redis","optional":true}],"imports":[{"symbol":"LimiterSession","correct":"from requests_ratelimiter import LimiterSession"},{"symbol":"LimiterAdapter","correct":"from requests_ratelimiter import LimiterAdapter"},{"symbol":"LimiterMixin","correct":"from requests_ratelimiter import LimiterMixin"},{"note":"RequestRate is part of pyrate-limiter, not requests-ratelimiter directly.","wrong":"from requests_ratelimiter import RequestRate","symbol":"RequestRate","correct":"from pyrate_limiter import RequestRate"},{"note":"Duration is part of pyrate-limiter, not requests-ratelimiter directly.","wrong":"from requests_ratelimiter import Duration","symbol":"Duration","correct":"from pyrate_limiter import Duration"}],"quickstart":{"code":"import os\nfrom requests_ratelimiter import LimiterSession\nfrom time import time\n\nsession = LimiterSession(per_second=5) # Limit to 5 requests per second\nstart = time()\n\nfor i in range(10):\n    try:\n        response = session.get('https://httpbin.org/get') # Or any other API endpoint\n        response.raise_for_status()\n        print(f'[t+{time()-start:.2f}] Sent request {i+1} (Status: {response.status_code})')\n    except Exception as e:\n        print(f'Request {i+1} failed: {e}')\n\n# Example with custom rate using pyrate-limiter objects\nfrom pyrate_limiter import RequestRate, Duration, Limiter\n# Limit to 10 requests per minute\ncustom_limiter_session = LimiterSession(limiter=Limiter(RequestRate(10, Duration.MINUTE)))\nstart_custom = time()\nfor i in range(5):\n    try:\n        response = custom_limiter_session.get('https://httpbin.org/get')\n        response.raise_for_status()\n        print(f'[t+{time()-start_custom:.2f}] Sent custom-limited request {i+1} (Status: {response.status_code})')\n    except Exception as e:\n        print(f'Custom-limited request {i+1} failed: {e}')\n","lang":"python","description":"This quickstart demonstrates how to use `LimiterSession` as a drop-in replacement for `requests.Session` to apply a simple rate limit. It also shows how to define more complex rate limits using `RequestRate` and `Duration` from the underlying `pyrate-limiter` library. The `httpbin.org/get` endpoint is used for demonstration purposes."},"warnings":[{"fix":"Upgrade your Python environment to 3.10 or newer.","message":"Dropped support for Python 3.8 and 3.9 as of version 0.9.0, aligning with upstream `pyrate-limiter` requirements. Requires Python >=3.10.","severity":"breaking","affected_versions":">=0.9.0"},{"fix":"For shared rate limits across threads, processes, or application restarts, use a persistent backend such as SQLite or Redis. This requires installing `requests-ratelimiter[sqlite]` or `requests-ratelimiter[redis]` and configuring the session with the appropriate backend.","message":"By default, each `LimiterSession` (and `LimiterAdapter`) operates independently, tracking rate limits only within its own instance. In multi-threaded environments, multiple processes, or web applications, this can lead to exceeding actual server-side rate limits.","severity":"gotcha","affected_versions":"All versions"},{"fix":"To ensure cache hits do not count towards the rate limit, the `CacheMixin` should typically be listed before `LimiterMixin` in the class inheritance. Example: `class CachedLimiterSession(CacheMixin, LimiterMixin, Session):`","message":"When combining `requests-ratelimiter` with other `requests`-based libraries (e.g., `requests-cache`) using mixins, the inheritance order of mixin classes is crucial. If rate-limiting is applied *before* caching, cache hits will still count against your rate limit.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Instead of `LimiterSession(rates=[RequestRate(5, Duration.SECOND)])`, use `LimiterSession(per_second=5)` or `LimiterSession(limiter=Limiter(RequestRate(5, Duration.SECOND)))`.","message":"In earlier versions, `LimiterSession` accepted a `rates` argument to define rate limits. This was replaced by direct `per_second`, `per_minute`, etc., arguments, or by passing a `Limiter` object. Using the old `rates` argument will raise an `InvalidParams` exception from `pyrate_limiter`.","severity":"breaking","affected_versions":"<0.9.0 (exact version unclear, but pre-0.9.0)"},{"fix":"Set `per_host=True` when initializing `LimiterSession` or `LimiterAdapter` if you need distinct rate limits for different API endpoints/hosts: `session = LimiterSession(per_second=5, per_host=True)`.","message":"The `per_host` parameter, available for both `LimiterSession` and `LimiterAdapter`, enables automatic tracking of rate limits separately for each host. If not enabled, a single rate limit applies across all hosts, which might not be the desired behavior for APIs with per-domain limits.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-13T00:00:00.000Z","next_check":"2026-07-12T00:00:00.000Z"}