Edit on GitHub

#  Event Hooks

Addons hook into mitmproxy’s internal mechanisms through event hooks. These are implemented on addons as methods with a set of well-known names. Many events receive Flow objects as arguments - by modifying these objects, addons can change traffic on the fly. For instance, here is an addon that adds a response header with a count of the number of responses seen:

"""Add an HTTP header to each response."""


class AddHeader:
    def __init__(self):
        self.num = 0

    def response(self, flow):
        self.num = self.num + 1
        flow.response.headers["count"] = str(self.num)


addons = [AddHeader()]
examples/addons/http-add-header.py

#  Available Hooks

The following addons list all available event hooks.

Lifecycle Events
def load(self, loader: mitmproxy.addonmanager.Loader):

Called when an addon is first loaded. This event receives a Loader object, which contains methods for adding options and commands. This method is where the addon configures itself.

def running(self):

Called when the proxy is completely up and running. At this point, you can expect all addons to be loaded and all options to be set.

def configure(self, updated: set[str]):

Called when configuration changes. The updated argument is a set-like object containing the keys of all changed options. This event is called during startup with all options in the updated set.

def done(self):

Called when the addon shuts down, either by being removed from the mitmproxy instance, or when mitmproxy itself shuts down. On shutdown, this event is called after the event loop is terminated, guaranteeing that it will be the final event an addon sees. Note that log handlers are shut down at this point, so calls to log functions will produce no output.

Connection Events
def client_connected(self, client: mitmproxy.connection.Client):

A client has connected to mitmproxy. Note that a connection can correspond to multiple HTTP requests.

Setting client.error kills the connection.

def client_disconnected(self, client: mitmproxy.connection.Client):

A client connection has been closed (either by us or the client).

Mitmproxy is about to connect to a server. Note that a connection can correspond to multiple requests.

Setting data.server.error kills the connection.

def server_connected(self, data: mitmproxy.proxy.server_hooks.ServerConnectionHookData):

Mitmproxy has connected to a server.

def server_disconnected(self, data: mitmproxy.proxy.server_hooks.ServerConnectionHookData):

A server connection has been closed (either by us or the server).

HTTP Events
def requestheaders(self, flow: mitmproxy.http.HTTPFlow):

HTTP request headers were successfully read. At this point, the body is empty.

def request(self, flow: mitmproxy.http.HTTPFlow):

The full HTTP request has been read.

Note: If request streaming is active, this event fires after the entire body has been streamed. HTTP trailers, if present, have not been transmitted to the server yet and can still be modified. Enabling streaming may cause unexpected event sequences: For example, response may now occur before request because the server replied with "413 Payload Too Large" during upload.

def responseheaders(self, flow: mitmproxy.http.HTTPFlow):

HTTP response headers were successfully read. At this point, the body is empty.

def response(self, flow: mitmproxy.http.HTTPFlow):

The full HTTP response has been read.

Note: If response streaming is active, this event fires after the entire body has been streamed. HTTP trailers, if present, have not been transmitted to the client yet and can still be modified.

def error(self, flow: mitmproxy.http.HTTPFlow):

An HTTP error has occurred, e.g. invalid server responses, or interrupted connections. This is distinct from a valid server HTTP error response, which is simply a response with an HTTP error code.

Every flow will receive either an error or an response event, but not both.

def http_connect(self, flow: mitmproxy.http.HTTPFlow):

An HTTP CONNECT request was received. This event can be ignored for most practical purposes.

This event only occurs in regular and upstream proxy modes when the client instructs mitmproxy to open a connection to an upstream host. Setting a non 2xx response on the flow will return the response to the client and abort the connection.

CONNECT requests are HTTP proxy instructions for mitmproxy itself and not forwarded. They do not generate the usual HTTP handler events, but all requests going over the newly opened connection will.

def http_connect_upstream(self, flow: mitmproxy.http.HTTPFlow):

An HTTP CONNECT request is about to be sent to an upstream proxy. This event can be ignored for most practical purposes.

This event can be used to set custom authentication headers for upstream proxies.

CONNECT requests do not generate the usual HTTP handler events, but all requests going over the newly opened connection will.

DNS Events
def dns_request(self, flow: mitmproxy.dns.DNSFlow):

A DNS query has been received.

def dns_response(self, flow: mitmproxy.dns.DNSFlow):

A DNS response has been received or set.

def dns_error(self, flow: mitmproxy.dns.DNSFlow):

A DNS error has occurred.

TCP Events
def tcp_start(self, flow: mitmproxy.tcp.TCPFlow):

A TCP connection has started.

def tcp_message(self, flow: mitmproxy.tcp.TCPFlow):

A TCP connection has received a message. The most recent message will be flow.messages[-1]. The message is user-modifiable.

def tcp_end(self, flow: mitmproxy.tcp.TCPFlow):

A TCP connection has ended.

def tcp_error(self, flow: mitmproxy.tcp.TCPFlow):

A TCP error has occurred.

Every TCP flow will receive either a tcp_error or a tcp_end event, but not both.

UDP Events
def udp_start(self, flow: mitmproxy.udp.UDPFlow):

A UDP connection has started.

def udp_message(self, flow: mitmproxy.udp.UDPFlow):

A UDP connection has received a message. The most recent message will be flow.messages[-1]. The message is user-modifiable.

def udp_end(self, flow: mitmproxy.udp.UDPFlow):

A UDP connection has ended.

def udp_error(self, flow: mitmproxy.udp.UDPFlow):

A UDP error has occurred.

Every UDP flow will receive either a udp_error or a udp_end event, but not both.

TLS Events
def tls_clienthello(self, data: mitmproxy.tls.ClientHelloData):

Mitmproxy has received a TLS ClientHello message.

This hook decides whether a server connection is needed to negotiate TLS with the client (data.establish_server_tls_first)

def tls_start_client(self, data: mitmproxy.tls.TlsData):

TLS negotation between mitmproxy and a client is about to start.

An addon is expected to initialize data.ssl_conn. (by default, this is done by mitmproxy.addons.tlsconfig)

def tls_start_server(self, data: mitmproxy.tls.TlsData):

TLS negotation between mitmproxy and a server is about to start.

An addon is expected to initialize data.ssl_conn. (by default, this is done by mitmproxy.addons.tlsconfig)

def tls_established_client(self, data: mitmproxy.tls.TlsData):

The TLS handshake with the client has been completed successfully.

def tls_established_server(self, data: mitmproxy.tls.TlsData):

The TLS handshake with the server has been completed successfully.

def tls_failed_client(self, data: mitmproxy.tls.TlsData):

The TLS handshake with the client has failed.

def tls_failed_server(self, data: mitmproxy.tls.TlsData):

The TLS handshake with the server has failed.

WebSocket Events
def websocket_start(self, flow: mitmproxy.http.HTTPFlow):

A WebSocket connection has commenced.

def websocket_message(self, flow: mitmproxy.http.HTTPFlow):

Called when a WebSocket message is received from the client or server. The most recent message will be flow.messages[-1]. The message is user-modifiable. Currently there are two types of messages, corresponding to the BINARY and TEXT frame types.

def websocket_end(self, flow: mitmproxy.http.HTTPFlow):

A WebSocket connection has ended. You can check flow.websocket.close_code to determine why it ended.

SOCKSv5 Events
def socks5_auth(self, data: mitmproxy.proxy.layers.modes.Socks5AuthData):

Mitmproxy has received username/password SOCKS5 credentials.

This hook decides whether they are valid by setting data.valid.

Advanced Lifecycle Events
def next_layer(self, data: mitmproxy.proxy.layer.NextLayer):

Network layers are being switched. You may change which layer will be used by setting data.layer.

(by default, this is done by mitmproxy.addons.NextLayer)

def update(self, flows: collections.abc.Sequence[mitmproxy.flow.Flow]):

Update is called when one or more flow objects have been modified, usually from a different addon.

def add_log(self, entry: mitmproxy.log.LogEntry):

Deprecated: Starting with mitmproxy 9, users should use the standard Python logging module instead, for example by calling logging.getLogger().addHandler().

Called whenever a new log entry is created through the mitmproxy context. Be careful not to log from this event, which will cause an infinite loop!