Reference

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.

Install
dotnet add package HaveIBeenPwned.Client
Aggregate client
IPwnedClient

Register the client

Call AddPwnedServices once at startup. Bind from configuration, or configure options inline. Every interface is registered as a singleton.

Bind from configurationC#
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:

Configure inlineC#
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.

InterfaceResponsibilityAuth
IPwnedClientEverything below, plus GetSubscriptionStatusAsync.Varies
IPwnedBreachesClientBreach catalogue and account exposure searches.Mixed
IPwnedPasswordsClientSHA-1 and NTLM password range checks.None
IPwnedPastesClientPaste lookups for an email address.API key
IPwnedDomainClientDomain verification and domain-wide search.API key
IPwnedStealerLogsClientStealer-log search by email or domain.API key + Pro

Configure HibpOptions

PropertyTypePurpose
ApiKeystring?Your HIBP API key. Required for account, paste, domain, and stealer-log searches. Leave null for password checks.
UserAgentstringSent on every request and required by HIBP. Defaults to ".NET HIBP Client/{version}".
SubscriptionLevelHibpSubscriptionLevel?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.

Core 1 - 5Pro 1 - 5High RPM 4000 - 24000
SubscriptionStatus (selected fields)
FieldTypeDescription
SubscriptionNamestringThe active plan and level, for example "Pro 2".
RpmintRequests-per-minute limit for account breach searches.
DomainSearchMaxBreachedAccountsintLargest domain you can search, by breached account count.
IncludesStealerLogsboolWhether the stealer-log APIs are available.
IncludesKAnonboolWhether k-anonymity email searches are available.
Read the current planC#
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:

Sample outputtext
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

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.

PwnedApiException
MemberTypeDescription
StatusCodeHttpStatusCode?The HTTP status returned by the API (inherited from HttpRequestException).
ResponseContentstring?The raw response body, when the API sent one.
RetryAfterTimeSpan?The delay HIBP asked you to wait, populated on 429 responses.
Status codes
CodeMeaning
200Success. The operation returns its normal result.
400The account, domain, or format was invalid.
401Missing or invalid API key on an authenticated call.
403No User-Agent, or the subscription lacks the requested capability.
404Not found. Documented operations map this to an empty array or null.
429Rate limited. Read PwnedApiException.RetryAfter and back off.
503Service unavailable. Retried by the resilience pipeline when configured.
Inspect failures where they happenC#
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
}