Rate Limiting Requests with aiohttp

Feb 22, 2024 ยท 3 min read

When building APIs and web services, it's often necessary to limit how many requests a client can make in a given period of time. This helps prevent abuse and reduces load on your servers.

The aiohttp library provides an easy way to accomplish this via the ThrottleConcurrency middleware. In this article, we'll explore how to use it to rate limit requests per second.

Why Rate Limit Requests

There are a few key reasons you may want to rate limit requests:

  • Prevent abuse and denial-of-service attacks
  • Ensure fair usage across all API consumers
  • Control server load and resources
  • For example, let's say you have an API that provides weather data. If you allow unlimited requests, a malicious client could bombard your servers with requests, potentially overwhelming them.

    By rate limiting to 50 requests per second, you can prevent this while still providing reasonable access.

    Using ThrottleConcurrency Middleware

    aiohttp's ThrottleConcurrency middleware allows limiting concurrent connections or requests to a particular number. Under the hood, it uses an Asyncio Semaphore to accomplish this.

    To use it, first install aiohttp:

    pip install aiohttp

    Then in your application code, import the middleware and set up your routes:

    from aiohttp import web
    from aiohttp.web import middleware
    
    async def handle(request):
      return web.Response(text="Hello world")
    
    app = web.Application(middlewares=[
      middleware.ThrottleConcurrency(50, 60)  
    ])
    app.router.add_get('/', handle)

    The ThrottleConcurrency middleware accepts two arguments:

  • limit - The maximum number of concurrent requests
  • period - The time period in seconds
  • So in this case, it is limited to 50 requests per 60 seconds. The period resets on each new request.

    You can adjust these limits as needed for your particular use case.

    Handling Exceeded Limits

    By default, if a client exceeds the defined limits, they will get a 503 Service Unavailable response.

    You can customize this by passing a status_code and text to the middleware:

    middleware.ThrottleConcurrency(50, 60,
                                  status_code=429,
                                  text="Too Many Requests")

    Now requests over the limit will get a 429 Too Many Requests response.

    Per Route Limits

    You can also apply different rate limit policies to different routes. This is useful when you have some endpoints that need higher or lower limits than others.

    For example:

    async def unprotected_route(request):
      # No rate limit
    
    @middleware.ThrottleConcurrency(30, 60)
    async def protected_route(request):
       # Apply 30 requests per 60 seconds
    
    app.router.add_get('/public', unprotected_route)  
    app.router.add_get('/api', protected_route)

    Here /public has no rate limiting, while /api is limited to 30 requests per minute.

    Tracking Usage

    When rate limiting, it can be useful to track usage so you can tweak the limits or identify potential abuse.

    You can write a middleware to increment a counter on each request and output metrics. For example:

    requests = 0  
    period_start = utcnow()
    
    @middleware
    async def tracker(request, handler):
        global requests, period_start
        
        requests += 1
        
        if utcnow() - period_start >= 60:
            print(f"{requests} requests in last 60 secs")
            requests = 0
            period_start = utcnow()
            
        return await handler(request)

    This allows logging request stats every 60 seconds to monitor usage.

    Recap

    Key points about rate limiting with aiohttp:

  • Use ThrottleConcurrency middleware to limit concurrent requests
  • Set limit and period based on your usage needs
  • Customize response code and text for exceeded limits
  • Apply different limits per route as needed
  • Track usage metrics to fine tune limits
  • By properly rate limiting your API, you can prevent abuse and instability from too many requests. aiohttp makes it easy to accomplish right within your web app.

    Browse by tags:

    Browse by language:

    The easiest way to do Web Scraping

    Get HTML from any page with a simple API call. We handle proxy rotation, browser identities, automatic retries, CAPTCHAs, JavaScript rendering, etc automatically for you


    Try ProxiesAPI for free

    curl "http://api.proxiesapi.com/?key=API_KEY&url=https://example.com"

    <!doctype html>
    <html>
    <head>
        <title>Example Domain</title>
        <meta charset="utf-8" />
        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    ...

    X

    Don't leave just yet!

    Enter your email below to claim your free API key: