The API, without the guesswork.
Register the client, pick the interface you need, and read exposure data with predictable, well-typed results. Every surface shares this shell and these conventions.
dotnet add package HaveIBeenPwned.ClientIPwnedClientRegister the client
Call AddPwnedServices once at startup. Bind from configuration, or configure options inline. Every interface is registered as a singleton.
using HaveIBeenPwned.Client;
var builder = WebApplication.CreateBuilder(args);
// Binds the "HibpOptions" section from appsettings.json.
builder.Services.AddPwnedServices(
builder.Configuration.GetSection(nameof(HibpOptions)));
var app = builder.Build();Prefer inline setup? Configure the same options with a delegate:
using HaveIBeenPwned.Client;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddPwnedServices(options =>
{
options.ApiKey = builder.Configuration["Hibp:ApiKey"];
options.SubscriptionLevel = HibpSubscriptionLevel.Pro2;
options.UserAgent = "MyApp/1.0";
});
var app = builder.Build();Which interface do I inject?
Inject the narrow interface for the surface you use, or IPwnedClient for all of them. They resolve to the same instance.
| Interface | Responsibility | Auth |
|---|---|---|
IPwnedClient | Everything below, plus GetSubscriptionStatusAsync. | Varies |
IPwnedBreachesClient | Breach catalogue and account exposure searches. | Mixed |
IPwnedPasswordsClient | SHA-1 and NTLM password range checks. | None |
IPwnedPastesClient | Paste lookups for an email address. | API key |
IPwnedDomainClient | Domain verification and domain-wide search. | API key |
IPwnedStealerLogsClient | Stealer-log search by email or domain. | API key + Pro |
Configure HibpOptions
| Property | Type | Purpose |
|---|---|---|
ApiKey | string? | Your HIBP API key. Required for account, paste, domain, and stealer-log searches. Leave null for password checks. |
UserAgent | string | Sent on every request and required by HIBP. Defaults to ".NET HIBP Client/{version}". |
SubscriptionLevel | HibpSubscriptionLevel? | Optional plan hint used by the Polly resilience package to shape rate-limit-aware retries. |
Subscription levels and limits
Set SubscriptionLevel to one of the HibpSubscriptionLevel tiers. Core plans cover breach, password, and domain search; Pro plans add stealer logs; High RPM plans raise the request ceiling. Read the live plan at runtime with GetSubscriptionStatusAsync.
| Field | Type | Description |
|---|---|---|
SubscriptionName | string | The active plan and level, for example "Pro 2". |
Rpm | int | Requests-per-minute limit for account breach searches. |
DomainSearchMaxBreachedAccounts | int | Largest domain you can search, by breached account count. |
IncludesStealerLogs | bool | Whether the stealer-log APIs are available. |
IncludesKAnon | bool | Whether k-anonymity email searches are available. |
public sealed class PlanInspector(IPwnedClient client)
{
public async Task ReportAsync()
{
SubscriptionStatus? status =
await client.GetSubscriptionStatusAsync();
Console.WriteLine(
$"{status?.SubscriptionName}: {status?.Rpm} rpm, " +
$"stealer logs {(status?.IncludesStealerLogs is true ? "on" : "off")}.");
}
}Running the snippet above prints:
Pro 2: 100 rpm, stealer logs on.Stealer-log operations require a Pro subscription or higher. Domain search size is capped by DomainSearchMaxBreachedAccounts on your plan.
Choose a surface
Breaches
Search accounts and browse breach metadata.
Pwned passwords
Range queries that keep the secret local.
Pastes
Find pastes that reference an email address.
Domains & stealer logs
Verify domains and search exposure.
Telemetry
Wire spans and metrics into OpenTelemetry.
Error behavior stays honest.
Documented 404 responses map to each operation's no-result shape. Every other non-success throws PwnedApiException, carrying the status, response body, and retry hint.
| Member | Type | Description |
|---|---|---|
StatusCode | HttpStatusCode? | The HTTP status returned by the API (inherited from HttpRequestException). |
ResponseContent | string? | The raw response body, when the API sent one. |
RetryAfter | TimeSpan? | The delay HIBP asked you to wait, populated on 429 responses. |
| Code | Meaning |
|---|---|
| 200 | Success. The operation returns its normal result. |
| 400 | The account, domain, or format was invalid. |
| 401 | Missing or invalid API key on an authenticated call. |
| 403 | No User-Agent, or the subscription lacks the requested capability. |
| 404 | Not found. Documented operations map this to an empty array or null. |
| 429 | Rate limited. Read PwnedApiException.RetryAfter and back off. |
| 503 | Service unavailable. Retried by the resilience pipeline when configured. |
try
{
var breaches = await client.GetBreachesForAccountAsync("account@example.com");
}
catch (PwnedApiException exception)
{
// Inspect status, body, and retry hint where the failure happened.
Console.WriteLine(exception.StatusCode); // e.g. TooManyRequests
Console.WriteLine(exception.RetryAfter); // e.g. 00:00:02
Console.WriteLine(exception.ResponseContent); // raw HIBP body, if any
}