Skip to content

Handling rate limits

The OpenAQ Python SDK tracks rate limit state automatically using the rate limit headers returned by the API. By default, when the rate limit is exhausted the client will call time.sleep() and block until the limit resets before continuing. This behavior is controlled by the auto_wait parameter on the OpenAQ client.

auto_wait is enabled by default. No additional configuration is required.

from openaq import OpenAQ
with OpenAQ(api_key="replace-me-with-a-valid-key",) as client:
# requests will block automatically if the rate limit is reached
locations = client.locations.list()

Setting auto_wait=False disables the automatic wait behavior. The client will instead raise a RateLimitError when the rate limit is exhausted, allowing you to handle it yourself.

from openaq import OpenAQ
from openaq.exceptions import RateLimitError
with OpenAQ(api_key="replace-me-with-a-valid-key", auto_wait=False) as client:
try:
locations = client.locations.list()
except RateLimitError as e:
print(f"Rate limit exceeded: {e}")
# handle the error — wait, retry, back off, etc.

Every response from the OpenAQ API includes headers describing the current state of your rate limit window. The SDK exposes these on each response object under the headers attribute:

├── headers
│ ├── x-ratelimit-limit: int | None
│ ├── x-ratelimit-remaining: int | None
│ ├── x-ratelimit-used: int | None
│ └── x-ratelimit-reset: int | None
HeaderDescription
x-ratelimit-limitMaximum number of requests allowed in the current window.
x-ratelimit-remainingRequests remaining before the limit is reached.
x-ratelimit-usedRequests made so far in the current window.
x-ratelimit-resetSeconds until the current rate limit window resets.

When auto_wait=False, you can read these headers directly to implement your own back-off or retry strategy:

from openaq import OpenAQ
from openaq.exceptions import RateLimitError
import time
with OpenAQ(api_key="replace-me-with-a-valid-key", auto_wait=False) as client:
while True:
try:
locations = client.locations.list()
break
except RateLimitError:
reset = client.locations.last_response.headers.get("x-ratelimit-reset")
wait = int(reset) if reset else 60
print(f"Rate limited. Retrying in {wait}s.")
time.sleep(wait)