Skip to content


A "hook" is a mechanism that allows developers to intercept and modify the behavior of a request flow at specific points. It allows to register custom functions by using decorator that are executed when certain events or conditions occur.

All request hooks are optional. There are three (3) types of hooks and two (2) modes, which can be used together.

  • Global hooks: These are run by the main python file. This requires the use of a main file.
  • Request scripting hooks (local): These are defined on each the request script.

Each hook accepts:

Hook Global Request scripting
hooks.pre_request async/sync function async/sync function
hooks.post_request async/sync function async/sync function
hooks.test Not available (sync only), unittest.TestCase class

Hooks API

Global and request specific hooks receives the same arguments. But the way of call changes, use ctx.hooks for local and zapy.requests.hooks for global.

Pre-request hooks.pre_request

The httpx_args parameter is a dict that should match the [email protected] arguments, such as:

async with httpx.AsyncClient() as client:

For example:

from zapy.requests import hooks, HttpxArguments

async def on_each_request(httpx_args: HttpxArguments):
    httpx_args['auth'] = ('alice', 'ecila123')
async def on_each_request(httpx_args):
    httpx_args['auth'] = ('alice', 'ecila123')

Post Request hooks.post_request

It receives a httpx response.

from zapy import requests, HttpxResponse
from import use_store

store = use_store()

async def on_each_request(httpx_response: HttpxResponse):
    store['payload'] =
async def on_response(httpx_response):
    print("post_request")['payload'] =

Test hooks.test

It allows providing assertions. This is specific for local hooks.

# test hook expects a unittest.TestCase class, cannot be async
import unittest

class TestResponse(unittest.TestCase):
    def test_status_code(self):
        self.assertEqual(self.response.status_code, 200)

Using metadata

It's possible to enrich pre_request and post_request hooks by adding the extra arguments. The extra arguments have to be annotated with a type hint.

Allowed type hints:

Argument Type Description
Metadata Optional Metadata object of the request
ZapyRequest Optional ZapyRequest object

For example, to perform a conditional logic based on the metadata tags.

from zapy import requests
from zapy.base.models import Metadata

async def on_each_request(httpx_args, metadata: Metadata):
    if 'basic_auth' in metadata.tags:
        httpx_args['auth'] = ('alice', 'ecila123')
from zapy.base.models import Metadata

async def on_pre_request(httpx_args, metadata: Metadata):
    if 'basic_auth' in metadata.tags:
        httpx_args['auth'] = ('alice', 'ecila123')

Request flow

Request flow