Skip to content

Tutorial: Capture And Replay HTTP Calls

This tutorial captures a real HTTP request from normal Python app startup, replays it locally, compares the replay report, and generates a pytest provider replay guard.

The example uses a public JSON endpoint. For private APIs, keep header values and secrets out of tutorial output. ReplayLab records safe header names by default, not header values.

ReplayLab matches HTTP replay calls by a deterministic request envelope: provider, method, canonical URL, query params, safe header names, and supported body content. Query values participate in matching; header values do not.

Supported public-alpha request shapes are:

  • query params as mappings, such as params={"page": 1}, or ordered two-item pairs, such as params=(("tag", "a"), ("tag", "b"))
  • request bodies through exactly one of json=..., text or bytes data=..., or text or bytes content=...
  • JSON, text, and bytes response bodies

ReplayLab still rejects file uploads, multipart bodies, streaming uploads, streaming downloads, and multiple request body sources in one call.

Setup

Install dependencies:

python -m venv .venv
source .venv/bin/activate
pip install replaylab requests

For local repo development before package publication:

uv sync --all-packages --all-groups
uv pip install requests

Startup Instrumentation

Create tutorial_http_app.py. The app keeps normal requests code. ReplayLab setup happens near startup, then handle.capture(...) scopes the HTTP work you want stored as one capsule.

import replaylab
import requests
from replaylab import CapturePayloadPolicy


def fetch_slideshow_title() -> str:
    response = requests.get(
        "https://httpbin.org/json",
        timeout=10,
    )
    response.raise_for_status()
    payload = response.json()
    return str(payload["slideshow"]["title"])


def main() -> None:
    handle = replaylab.init(
        project_name="tutorial-http",
        auto_patch_integrations=("requests",),
        capture_payload_policy=CapturePayloadPolicy.FULL,
    )

    with handle.capture(
        "httpbin_slideshow_lookup",
        labels=("tutorial", "http"),
    ) as capture:
        print(fetch_slideshow_title())

    if capture.capsule is not None:
        print(f"ReplayLab capsule: {capture.capsule.capsule_path}")


if __name__ == "__main__":
    main()

Capture Scope

Capture uses your normal app command. There is no ReplayLab wrapper process in this production-style path.

uv run python tutorial_http_app.py

What good looks like:

Sample Slide Show
ReplayLab capsule: .replaylab/capsules/<capsule_id>

Capsule List

uv run replaylab capsule list --local-store-root .replaylab

Pick the capsule whose integrations include requests, auto_patch, and same_process.

Inspect

uv run replaylab capsule inspect <capsule_id> --local-store-root .replaylab

What good looks like:

Boundaries: 1
Providers: requests
Payloads: 2
Boundary 0: http requests GET https://httpbin.org/json (succeeded)

Replay

Replay is local regression tooling. It runs the same application command under replaylab replay; when the request matches the capsule, ReplayLab serves a ReplayHttpResponse instead of calling the live HTTP provider. The app keeps the same startup replaylab.init(...) and handle.capture(...) code in replay mode; ReplayLab treats that capture scope as a no-op while the CLI-owned replay runtime serves provider calls.

uv run replaylab replay <capsule_id> \
  --local-store-root .replaylab \
  --auto-patch-integrations requests \
  --report-id replay_tutorial_http \
  -- python tutorial_http_app.py

Compare

uv run replaylab report compare \
  <capsule_id> \
  .replaylab/replays/replay_tutorial_http/report.json \
  --local-store-root .replaylab

What good looks like:

Status: succeeded
Expected boundaries: 1
Replayed: 1
Problems: 0

Generate-Test

uv run replaylab generate-test <capsule_id> \
  --output tests/regression/test_tutorial_http_replay.py \
  --fixture-root tests/fixtures/replaylab/capsules \
  --app-root . \
  --auto-patch-integrations requests \
  -- python tutorial_http_app.py

Run the generated test:

uv run pytest tests/regression/test_tutorial_http_replay.py