Vcr.HttpRecorder
3.1.4
dotnet add package Vcr.HttpRecorder --version 3.1.4
NuGet\Install-Package Vcr.HttpRecorder -Version 3.1.4
<PackageReference Include="Vcr.HttpRecorder" Version="3.1.4" />
<PackageVersion Include="Vcr.HttpRecorder" Version="3.1.4" />
<PackageReference Include="Vcr.HttpRecorder" />
paket add Vcr.HttpRecorder --version 3.1.4
#r "nuget: Vcr.HttpRecorder, 3.1.4"
#:package Vcr.HttpRecorder@3.1.4
#addin nuget:?package=Vcr.HttpRecorder&version=3.1.4
#tool nuget:?package=Vcr.HttpRecorder&version=3.1.4
Vcr.HttpRecorder
.NET HttpClient integration tests made easy.
HttpRecorder is an HttpMessageHandler that can record and replay HTTP interactions through the standard HttpClient . This allows the creation of HTTP integration tests that are fast, repeatable and reliable.
Interactions are recorded using the HTTP Archive format standard, so that they are easily manipulated by your favorite tool of choice.
π This is a maintained fork of the original nventive/HttpRecorder.
It includes bug fixes, support for modern .NET versions, and new features like concurrent context support.
<details> <summary>π Table of Contents</summary>
- Recommended Setup (ASP.NET Core)
- Install via NuGet
- Manual Setup with Delegating Handler
- Features
- Compared to WireMock
</details>
Recommended Setup (ASP.NET Core Integration Testing)
If you're using WebApplicationFactory, this is the simplest and most powerful way to enable automatic recording and replaying across all HttpClients:
[Fact]
public async Task MyApiTest()
{
using var context = new HttpRecorderConcurrentContext((_, _) => new HttpRecorderConfiguration
{
Mode = HttpRecorderMode.Auto, // Automatically records or replays
});
var client = webAppFactory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddHttpRecorderConcurrentContextSupport(); // Injects the handler globally
});
}).CreateClient();
var response = await client.GetAsync("/api/my-endpoint");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
β No need to manually configure HttpClient
β All HttpClients use the recorder automatically
β .har files are stored per test method
β Supports parallel test execution
Install via NuGet
Install-Package HttpRecorder
Using the Delegating Handler Manually
If you want to apply HttpRecorder to a specific HttpClient only β without affecting the global DI container β you can use the delegating handler directly:
var interactionPath = "fixtures/test.har";
var client = new HttpClient(new HttpRecorderDelegatingHandler(interactionPath)
{
InnerHandler = new HttpClientHandler()
})
{
BaseAddress = new Uri("https://reqres.in/")
};
This is useful if you need more granular control over which clients are recorded.
π Tip: You can use CallerMemberName + CallerFilePath to automatically name har files per test.
Features
Modes
Auto(default): Replay if cassette exists, otherwise recordRecord: Always recordReplay: Always replay (throws if file is missing)Passthrough: Bypass recorder, make real requests
You can override the mode with the HTTP_RECORDER_MODE environment variable β useful in CI.
Matching Behavior
When replaying, HttpRecorder uses a rule-based matcher to determine which recorded response to return for a given request.
By default, if you donβt configure a matcher, it behaves exactly as if you had written:
matcher = RulesMatcher.MatchOnce
.ByHttpMethod()
.ByRequestUri(UriPartial.Path);
This means:
Requests are matched by HTTP method and the path part of the URI
Each recorded request is used once and in order
If your test sends two identical requests, both must have been recorded
If there are not enough matching requests in the .har file during replay, the test will fail.
Custom Matchers
You can customize the matching logic to match multiple times or add more rules β for example:
matcher = RulesMatcher.MatchMultiple
.ByHttpMethod()
.ByRequestUri(UriPartial.Path)
.ByHeader("Authorization");
matcher = RulesMatcher.MatchOnce
.ByHttpMethod()
.ByRequestUri(UriPartial.Path)
.ByContent(); // matches by binary content
You can also match by deserialized JSON:
matcher = RulesMatcher.MatchOnce
.ByHttpMethod()
.ByJsonContent<MyRequestDto>();
π If none of the built-in rules suit your needs, you can implement a custom IRequestMatcher.
Anonymization
Mask sensitive fields before saving:
var anonymizer = RulesInteractionAnonymizer.Default
.AnonymizeRequestHeader("Authorization");
External HAR Support
You can use .har files recorded with tools like:
Fiddler
Chrome DevTools
Postman
Just pass the file path into the handler.
Custom Storage
You can override how and where interactions are stored via IInteractionRepository.
Compared to WireMock
WireMock is a powerful tool, but sometimes it's more than you need β especially for simple, deterministic testing of external API calls.
| Feature | WireMock | Vcr.HttpRecorder |
|---|---|---|
| Requires mock server | β | β |
| Requires hand-written stubs | β | β (records real responses) |
| Easily test external API logic | β οΈ manual setup needed | β out of the box |
| Works with WebApplicationFactory | β οΈ extra wiring | β built-in support |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Http (>= 9.0.1)
- System.Text.Json (>= 9.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.1.4 | 2,019 | 9/19/2026 |
| 3.1.4-concurrent-contect-as... | 48 | 6/13/2026 |
| 3.1.4-beta.16 | 62 | 9/18/2026 |
| 3.1.4-beta.12 | 61 | 9/16/2026 |
| 3.1.4-beta.10 | 182 | 6/30/2026 |
| 3.1.4-beta.6 | 120 | 5/18/2026 |
| 3.1.3 | 6,349 | 5/18/2026 |
| 3.1.3-beta.10 | 74 | 5/18/2026 |
| 3.1.3-beta.4 | 14,152 | 4/6/2025 |
| 3.1.3-beta.3 | 223 | 4/5/2025 |
| 3.1.3-beta.2 | 130 | 4/5/2025 |
| 3.1.3-beta.1 | 126 | 4/5/2025 |
| 3.1.2 | 5,659 | 4/5/2025 |
| 3.1.2-beta.1 | 131 | 4/5/2025 |
| 3.1.1 | 226 | 4/5/2025 |
| 3.1.1-beta.8 | 119 | 4/5/2025 |
| 3.1.1-beta.7 | 139 | 4/5/2025 |
| 3.1.1-beta.6 | 132 | 4/5/2025 |
| 3.1.1-beta.5 | 132 | 4/5/2025 |
| 3.1.1-beta.4 | 132 | 4/5/2025 |