Record and Replay HTTP Traffic with mitmproxy
Capture real client traffic into a flow file with mitmproxy, edit selected requests, and replay them deterministically against staging to reproduce bugs.
Task
Record production-like traffic, save it as a flow file, and replay it against a test environment to reproduce an intermittent bug.
When to use this
A bug appears once a week in a client nobody controls. Support sends screenshots, engineering cannot reproduce it, and the exact request sequence is unknown.
Prerequisites
- mitmproxy installed on a machine that can see the client traffic
- A client configured to use the proxy, or a transparent capture point
- A staging environment that tolerates replayed writes
Steps
1. Record a session while reproducing the user journey.
mitmdump -w session.flows --set flow_detail=1Expected output: A flow file is written and each request prints a one-line summary as it passes through.
2. Inspect the capture and locate the requests that matter.
mitmdump -nr session.flows --view-filter "~u /api/checkout"Expected output: Only checkout requests are listed, with methods, status codes, and sizes, giving a map of the failing journey.
3. Replay the recorded sequence against staging.
mitmdump -n -s redirect_to_staging.py -r session.flowsExpected output: All recorded requests are re-sent to staging in order, producing the same sequence the client originally made.
4. Redirect hosts with a small addon script.
class RedirectToStaging:
def request(self, flow):
if flow.request.pretty_host == "api.example.com":
flow.request.host = "staging.example.com"
addons = [RedirectToStaging()]
Expected output: The addon rewrites the Host before sending, so the replay lands on staging without editing the flow file.
5. Repeat the replay until the intermittent bug shows.
for i in $(seq 1 20); do mitmdump -n -s redirect_to_staging.py -r session.flows -q; doneExpected output: One of the runs triggers the failure, and the flow file plus the loop count document the exact reproduction steps.
Troubleshooting
Problem
Client refuses the proxy certificate
Solution
Install the mitmproxy CA certificate into the client trust store, or use a client that allows skipping verification for the test run.
Problem
Replay fails on authentication
Solution
Recorded tokens expired; either replay quickly after recording, or use the addon to swap in a long-lived staging token before sending.
Problem
Replayed writes corrupt staging data
Solution
Point the replay at a disposable environment and reset it after each loop; never replay write traffic against production.
Limitations
- Time-sensitive behavior can differ on replay because timestamps and server state move on between record and replay.
- WebSockets and HTTP/2 push streams are captured but their replay fidelity is lower than plain request/response flows.
Turn a screenshot into a reproduction
When the failing client is a mobile app or a third-party integration you cannot debug, the fastest path to a reproduction is to record what it actually sends. mitmproxy sits between the client and the server, writes every request and response into a flow file, and can later replay that exact sequence against any environment. The bug stops being a description and becomes an artifact you can loop until it breaks.
# Record
mitmdump -w session.flows
# Replay against another host with an addon
mitmdump -n -s redirect_to_staging.py -r session.flows
Filter before you read
A real session contains hundreds of requests for analytics, fonts, and pings that bury the interesting ones. Use a view filter such as tilde-u slash api slash checkout to narrow the listing before reading it. The flow file stays complete; only the display is filtered.
Replay loops expose races
Intermittent bugs often depend on timing between two requests. Replaying the whole recorded sequence twenty times in a tight loop changes those timings far more than clicking around manually does, and the loop count becomes a measurable reproduction rate instead of a vague sometimes.