Record and Replay HTTP Requests to Mock a Flaky Third-Party API (2026)

Updated 2026-08-22

Your test suite is green on your machine and red in CI, and neither result is about your code. A payment provider's sandbox is throwing 502s. A partner API is rate-limiting the build agent. Someone's staging environment is down for the third day running.

The fix is old and well understood: record the real response once, replay it afterwards. What has changed is where you can do the recording.

The pattern already has a name

If you have written Ruby you have probably used VCR. Python has vcrpy, Node has nock and polly.js, Go has go-vcr. They all do the same thing: intercept HTTP at the library level, write the response to a cassette file, and serve that file on the next run.

It works. It is also why most teams end up with three of them.

Each cassette library binds to one HTTP client in one language. A Python service and a Node service testing against the same vendor keep two independent sets of recordings that drift apart. The cassettes live in the repo of whoever recorded them, so a fixture your teammate captured is not one you can use. And nothing records the traffic your mobile app or your CI container makes, because there is no library in the loop to hook.

Recording one layer down

An HTTP proxy sits below all of that. It sees the request no matter which language emitted it, which is why proxies are how you debug mobile and third-party traffic in the first place.

Proxycept is a hosted proxy, so recording is the thing it already does. Every request through a profile is captured with its response. Save as mock turns one of those captured flows into a mock route: same method, same host, same path, the recorded status, headers and body played back.

The practical differences from a cassette file:

  • Any language, any client. curl, requests, axios, an iOS app, a Playwright run: if it goes through the proxy it can be recorded, and there is nothing to install per language.
  • Shared, not local. The recording lives in a workspace. A mock your colleague captured on Tuesday is one your CI job can replay on Wednesday.
  • Same endpoint for record and replay. Your test config points at the proxy either way; flipping the mock server on is what changes, not your code.

Doing it

  1. Start a profile and point the client at it. That is the same HTTPS_PROXY you would set for any proxy. No SDK, no code change.
  2. Make the real call once, while the dependency is healthy. The flow shows up in the session with its response.
  3. Open the flow and choose "Save as mock." Pick the profile the route should live on.
  4. Turn the mock server on for that profile.
  5. Run your tests. The recorded response is served without the request leaving the proxy.

To capture a whole session at once, use Save all as mocks. It walks the flows, skips the ones it cannot promote, and tells you which ones and why rather than silently dropping them.

What it does not do

Stated plainly, because these change whether the approach fits your suite:

  • A route matches the path including its query string. A mock recorded from /v1/accounts?page=1 will not answer /v1/accounts?page=2. That is a second recording. This is deliberate: stripping the query would make the route match calls it never saw, and that failure is far harder to debug than a miss. If your dependency is called with widely varying parameters, record the calls your tests actually make.
  • JSON-RPC recordings are body-aware. In addition to method, host and path, Proxycept scopes a promoted JSON-RPC route to its method; tools/call routes are scoped to params.name as well. That lets several MCP operations share POST /mcp without one recording answering every call. Other body protocols are not inferred yet. GraphQL operationName matching, for example, is not supported.
  • Responses are captured up to 64 KB. A body at that ceiling cannot be proven complete, so it is refused rather than promoted as a truncated fixture that fails confusingly later.
  • Only successful responses promote. If the dependency was already returning 503 when you captured, there is nothing worth replaying.
  • A profile answers for one host. The first promotion scopes the profile to the host it came from, and the comparison is exact: API.Example.com and api.example.com are two different hosts.

When a cassette library is still the right answer

If you have exactly one service in exactly one language, and its tests already run without network access, a library-level cassette is less machinery and you should keep it. vcrpy in a Python monolith is a good tool and a proxy adds a moving part you did not need.

The proxy approach earns its keep when the recording has to be shared, when more than one language is involved, or when the traffic comes from something you cannot hook: a mobile build, a browser test, a container in CI.

The honest summary

Recording and replaying HTTP is not a new idea, and Proxycept did not invent it. What it changes is the layer: one recording, usable by every language and every teammate, instead of a cassette file per repo per runtime.

If someone else's downtime has failed your build this month, that is the problem this solves.

Start free →

Try Proxycept free

One hosted proxy endpoint for every device, emulator, and CI runner. Shared captures, no per-machine install.

Start free