python LogoHTTP Client with httpx

An HTTP client is a software application or a library that sends HTTP requests to a server and receives HTTP responses. It acts as the initiator of a request to a server, which then processes the request and sends back a response. Common operations include fetching web pages, submitting forms, interacting with APIs, and uploading files.

`httpx` is a modern, fully featured HTTP client for Python 3, providing both synchronous and asynchronous APIs. It's designed to be a spiritual successor to the popular `requests` library, but with several key advancements:

1. Asynchronous Support: `httpx` is built from the ground up to support `async/await`, making it ideal for high-performance network applications and integrating seamlessly with async web frameworks like FastAPI and Starlette.
2. HTTP/2 Support: It natively supports HTTP/2, allowing for more efficient communication over the same connection.
3. Type Hinting: `httpx` is fully type-hinted, improving code readability, maintainability, and enabling better static analysis.
4. Intuitive API: Its API is very similar to `requests`, making it easy for developers familiar with `requests` to transition to `httpx`.
5. Rich Request/Response Objects: Provides comprehensive objects for both requests and responses, allowing detailed inspection of headers, body, status, etc.
6. Streaming: Supports streaming request and response bodies, useful for large file uploads/downloads.
7. Client Sessions: Offers `httpx.Client` for synchronous operations and `httpx.AsyncClient` for asynchronous operations, which manage connection pools and allow for persistent settings across multiple requests.

To use `httpx`, you first need to install it: `pip install httpx`.

`httpx` is an excellent choice for any modern Python project that requires robust, high-performance, and maintainable HTTP communication, whether synchronous or asynchronous.

Example Code

import httpx
import asyncio

 --- 1. Installation ---
 pip install httpx

 --- 2. Synchronous Usage ---

print("--- Synchronous HTTP GET Request ---")
try:
    response = httpx.get("https://jsonplaceholder.typicode.com/todos/1")
    response.raise_for_status()  Raises an exception for 4XX/5XX responses
    print(f"Status Code: {response.status_code}")
    print(f"Headers: {response.headers['Content-Type']}")
    print(f"Body (JSON): {response.json()}")
except httpx.RequestError as exc:
    print(f"An error occurred while requesting {exc.request.url!r}: {exc}")
except httpx.HTTPStatusError as exc:
    print(f"Error response {exc.response.status_code} while requesting {exc.request.url!r}: {exc}")

print("\n--- Synchronous HTTP POST Request ---")
post_data = {"title": "foo", "body": "bar", "userId": 1}
try:
    response = httpx.post("https://jsonplaceholder.typicode.com/posts", json=post_data)
    response.raise_for_status()
    print(f"Status Code: {response.status_code}")
    print(f"Body (JSON): {response.json()}")
except httpx.RequestError as exc:
    print(f"An error occurred while requesting {exc.request.url!r}: {exc}")
except httpx.HTTPStatusError as exc:
    print(f"Error response {exc.response.status_code} while requesting {exc.request.url!r}: {exc}")


 --- 3. Asynchronous Usage ---

async def fetch_async_data():
    print("\n--- Asynchronous HTTP GET Request ---")
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get("https://jsonplaceholder.typicode.com/todos/2")
            response.raise_for_status()
            print(f"Status Code: {response.status_code}")
            print(f"Body (JSON): {response.json()}")
        except httpx.RequestError as exc:
            print(f"An error occurred while requesting {exc.request.url!r}: {exc}")
        except httpx.HTTPStatusError as exc:
            print(f"Error response {exc.response.status_code} while requesting {exc.request.url!r}: {exc}")

    print("\n--- Asynchronous HTTP POST Request ---")
    async with httpx.AsyncClient() as client:
        post_data_async = {"title": "async_foo", "body": "async_bar", "userId": 2}
        try:
            response = await client.post("https://jsonplaceholder.typicode.com/posts", json=post_data_async)
            response.raise_for_status()
            print(f"Status Code: {response.status_code}")
            print(f"Body (JSON): {response.json()}")
        except httpx.RequestError as exc:
            print(f"An error occurred while requesting {exc.request.url!r}: {exc}")
        except httpx.HTTPStatusError as exc:
            print(f"Error response {exc.response.status_code} while requesting {exc.request.url!r}: {exc}")

if __name__ == "__main__":
    asyncio.run(fetch_async_data())