Gender API for C# and .NET
Add gender from a name, email or username to a .NET service or CRM integration, with the probability and sample size kept in your own model.
100 free credits every day. No card.
Install and make the first request
The NameGender package targets .NET Standard 2.0 and .NET 8, so the same client runs in a current ASP.NET Core service and in an older .NET Framework 4.6.2 application, which is where many CRM and HR integrations still live. Keep the API key in user secrets during development and in a vault or an environment variable in production, never in appsettings.json that is committed to source control.
Every method is asynchronous and takes a CancellationToken. A result is a GenderResponse: Gender is "male", "female" or null, Probability is an integer from 0 to 100, SampleSize is the number of recorded people the answer rests on, and Confidence and Source say how it was reached. Model Gender as a nullable string in your own types. Null is a successful answer that the evidence was insufficient, not a failure to be hidden behind a default.
Pass the country as an ISO two-letter code whenever the record has one. Andrea is a man in Italy and a woman in Germany, and without a hint the API returns the globally dominant reading.
// dotnet add package NameGender
using NameGender;
using var client = new NameGenderClient(Environment.GetEnvironmentVariable("NAMEGENDER_API_KEY")!);
var result = await client.NameAsync("Andrea", new LookupOptions { Country = "IT" });
Console.WriteLine(result.Gender); // null when the evidence is insufficient
Console.WriteLine(result.Probability); // 0-100
Console.WriteLine(result.SampleSize);
Copy failed. Select and copy the text.
Bulk lookups inside a service
Create one NameGenderClient and reuse it; it is safe to share across threads. In an application that already uses dependency injection, hand it an HttpClient from IHttpClientFactory so connection pooling and handler lifetimes are managed in one place, and register the client as a singleton.
BulkAsync sends up to 100 values per request and returns the results in the order sent, one credit each. For a larger list, look up each distinct name once in chunks of 100 and join the answers back. A contact export repeats the same first names many times, and paying for each repetition buys nothing. Keep the country in the join key when your records span markets.
Run enrichment in a background worker or a queued job, not in the request path of a user-facing page. Persist completed chunks so a restart resends one chunk instead of the whole export.
// Enumerable.Chunk needs .NET 6 or later
var distinct = contacts.Select(c => c.FirstName).Distinct().ToList();
var byName = new Dictionary<string, GenderResult>();
foreach (var chunk in distinct.Chunk(100))
{
var batch = await client.BulkAsync(chunk, new LookupOptions { Country = "DE" }, cancellationToken: ct);
foreach (var row in batch.Results)
{
byName[row.Query] = row;
}
}
Copy failed. Select and copy the text.
Handle errors by what they mean
Success is the HTTP status. Any other response throws NameGenderException, which carries the status code, a machine-readable Code such as no_credits, invalid_key or rate_limited, the RequestId to quote to support, and RetryAfter when the API asked you to slow down. Catch by Code rather than by parsing the message.
Retry only what can succeed on a second attempt: rate_limited after the RetryAfter delay, and network or server errors with a bounded exponential backoff. An invalid key or malformed input will fail the same way every time and belongs in an alert or a review queue, not a loop.
Keep an unknown gender and a failed request apart all the way through your code. One means the API answered and the evidence was thin; the other means no answer arrived. Log the RequestId and the status, never the API key or the full customer record.
try
{
var result = await client.NameAsync(name, cancellationToken: ct);
}
catch (NameGenderException e) when (e.Code == "rate_limited")
{
await Task.Delay(e.RetryAfter ?? TimeSpan.FromSeconds(1), ct);
}
catch (NameGenderException e) when (e.Code == "no_credits")
{
logger.LogWarning("Out of credits, request {RequestId}", e.RequestId);
}
Copy failed. Select and copy the text.
Questions
Which .NET versions are supported?
The package targets .NET Standard 2.0 and .NET 8, so it runs on .NET Framework 4.6.2 and later, .NET Core 2.0 and later, and every current .NET release.
Is the client thread-safe?
Yes. Create one instance and share it, or register it as a singleton with an HttpClient from IHttpClientFactory.
How many names can one request carry?
Up to 100. For larger lists, send the distinct names in chunks of 100 and join the results back to your records.
Where is the source?
On GitHub at anpekesen/namegender-dotnet, under the MIT license. Releases are published to NuGet from tagged commits by GitHub Actions, without a stored API key.
Related pages
Call the NameGender API from Python, send country-aware and bulk lookups, handle unknown results, and keep probability and evidence fields in your pipeline.
Use the NameGender JavaScript client in Node.js, Deno or Bun. See country-aware lookups, bulk requests, error handling and safe API-key placement.
Append a gender column to a customer list, CRM export or lead database, with a confidence field you can filter on and no monthly reset on purchased credits.
A working checklist for integrating a name gender API: deduplicate, batch by country, retry only what can succeed, store the evidence, and set a threshold.
Reading the gender field alone discards everything that says whether to believe it. What each response field means and the thresholds behind confidence.
Check it against your own list
Every number on this page is reproducible with a free key. If your data breaks it, that is the more interesting result.