Comparison of HTTP Asynchronous Calls: httpx vs aiohttp

Core Features

httpx

  • Modern API Design: Inspired by the synchronous libraryrequests, the API is intuitive and easy to use.

  • HTTP/2 Support: Natively supports HTTP/2, which can enhance communication efficiency with compatible servers.

  • Sync and Async Compatibility: Supports both synchronous (httpx.Client) and asynchronous (httpx.AsyncClient) interfaces, suitable for mixed scenarios.

aiohttp

  • High Performance: Designed to be lightweight, optimized for high throughput scenarios, and generally faster than httpx.

  • Flexible Configuration: Provides fine-grained control over HTTP connections, headers, and sessions, suitable for complex requirements.

  • Mature Ecosystem: As an older library, it has an active community, rich documentation, and supports complex scenarios.

Basic Usage

httpx

import httpx
import asyncio
async def fetch_data():
    async with httpx.AsyncClient() as client:
        response = await client.get("https://api.example.com")
        return response.json()
asyncio.run(fetch_data())

aiohttp

import aiohttp
import asyncio
async def fetch_data():
    async with aiohttp.ClientSession() as session:
        response = await session.get("https://api.example.com")
        return await response.json()
asyncio.run(fetch_data())

High Concurrency Code Example:

import aiohttp
import asyncio
async def fetch_url(session, url):
    """Send a single POST request and return JSON result"""
    async with session.post(url, json={"key": "value"}) as response:
        return await response.json()
async def main():
    """High concurrency request example"""
    url = "https://api.example.com/data"  # Replace with your API address
    async with aiohttp.ClientSession() as session:  # Can be replaced with httpx for comparison
        # Concurrently send 10 requests
        tasks = [fetch_url(session, url) for _ in range(10)]
        results = await asyncio.gather(*tasks)
        # Output results
        for result in results:
            print(result)
if __name__ == "__main__":
    asyncio.run(main())

JSON Requests

  • Both httpx and aiohttp support the “json=dict” syntax:

response = await client.post("https://api.example.com", json=payload)  # Automatically sets Content-Type: application/json

Do not follow json= with a json.dumps string, or the server may return errors like [422 Unprocessable Entity].

  • Using data to manually serialize JSON:

import json
# httpx
async with httpx.AsyncClient() as client:
    payload = json.dumps({"key": "value"})
    response = await client.post("https://api.example.com", data=payload)  # Automatically sets Content-Type: application/json
# aiohttp
async with aiohttp.ClientSession() as session:
    payload = json.dumps({"key": "value"})
    response = await session.post("https://api.example.com", data=payload, headers={"Content-Type": "application/json"})  # Must manually set headers

When using the data parameter and manually serialized JSON (like json.dumps), httpx will automatically add the Content-Type header, while aiohttp requires manual setting.

Resource Management

# Safe: Context manager automatically cleans up resources
async with httpx.AsyncClient() as client:
    response = await client.post("https://api.example.com", json={"key": "value"})
# Safe: Context manager automatically cleans up resources
async with aiohttp.ClientSession() as session:
    response = await session.post("https://api.example.com", json={"key": "value"})
# Unsafe: Manual session management may lead to leaks
session = aiohttp.ClientSession()
response = await session.post("https://api.example.com", json={"key": "value"})
await session.close()  # Must explicitly close

Performance

  • aiohttp: Due to its lightweight design and highly optimized connection handling, it is usually 5-10% faster thanhttpx in high throughput scenarios (based on community benchmarks).

  • httpx: Due to its support for HTTP/2 and richer features, its performance is slightly lower thanaiohttp, but for small to medium projects, the difference is negligible.

Applicable Scenarios

  • Choose httpx:

    • When an intuitive API similar torequests is needed, suitable for rapid development.

    • When the project involves HTTP/2 or frequent JSON requests.

    • When a mixed scenario of synchronous and asynchronous is required.

  • Choose aiohttp:

    • When extreme performance is required, suitable for high throughput applications.

    • When developing both client-side and server-side asynchronous applications.

    • When fine-grained control over connections and headers is preferred.

Leave a Comment