Skip to content

Requests - Event Hooks

The requests library provides an event hook system that allows you to attach callback functions to be executed at certain points in the request-response cycle. The primary hook available is 'response', which is triggered after a response has been received from the server but before it’s returned to the calling code.

This feature can be useful for tasks like logging, custom metrics collection, or modifying response objects on the fly. However, for many common use cases, simpler alternatives like wrapper functions or custom Session objects might be more appropriate.

To add a callback, you pass a dictionary to the hooks parameter. The key is the event name (e.g., 'response'), and the value is the callback function (or a list of functions).

A hook callback function receives the response object as its first argument, followed by *args and **kwargs passed to the original request method (e.g., get, post).

import requests
def log_response_url(response, *args, **kwargs):
print(f"Hook: Request to {response.url} completed with status {response.status_code}")
# You can inspect or modify the response here if needed
# For example: response.hook_processed = True
print("Making request with a single hook...")
response_data = requests.get(
'https://jsonplaceholder.typicode.com/todos/1',
hooks={'response': log_response_url}
)
print("\nResponse Content:")
print(response_data.json())
Making request with a single hook...
Hook: Request to https://jsonplaceholder.typicode.com/todos/1 completed with status 200
Response Content:
{'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}

In this example, log_response_url is called immediately after the response for the GET request is received.

You can also provide a list of callback functions for a single hook. They will be executed in the order they appear in the list.

import requests
def print_url(response, *args, **kwargs):
print(f"Hook 1: URL - {response.url}")
def print_status(response, *args, **kwargs):
print(f"Hook 2: Status Code - {response.status_code}")
print("Making request with multiple hooks...")
response_data = requests.get(
'https://jsonplaceholder.typicode.com/todos/2',
hooks={'response': [print_url, print_status]}
)
print("\nResponse Content:")
print(response_data.json())
Making request with multiple hooks...
Hook 1: URL - https://jsonplaceholder.typicode.com/todos/2
Hook 2: Status Code - 200
Response Content:
{'userId': 1, 'id': 2, 'title': 'quis ut nam facilis et officia qui', 'completed': False}

Hooks can also be attached to a Session object. These hooks will then apply to all requests made using that session.

import requests
def session_hook_logger(response, *args, **kwargs):
print(f"Session Hook: Request to {response.url} got status {response.status_code}")
# Let's add a custom attribute to the response
response.custom_processed_by_hook = True
session = requests.Session()
# Hooks on a session are managed as a list, so you append to it.
session.hooks['response'].append(session_hook_logger)
print("Making request with a session hook...")
response1 = session.get('https://jsonplaceholder.typicode.com/todos/3')
print(f"Response 1 processed by hook: {hasattr(response1, 'custom_processed_by_hook') and response1.custom_processed_by_hook}")
response2 = session.get('https://jsonplaceholder.typicode.com/todos/4')
print(f"Response 2 processed by hook: {hasattr(response2, 'custom_processed_by_hook') and response2.custom_processed_by_hook}")
Making request with a session hook...
Session Hook: Request to https://jsonplaceholder.typicode.com/todos/3 got status 200
Response 1 processed by hook: True
Session Hook: Request to https://jsonplaceholder.typicode.com/todos/4 got status 200
Response 2 processed by hook: True

While powerful, event hooks are an advanced feature. Ensure they are the right tool for your needs, as they can sometimes make request logic harder to follow. For more details, see the official documentation on Event Hooks.