probability, confidence and total_names: reading a gender response properly
A gender lookup returns nine fields. Most integrations use one.
That is understandable — you asked for a gender and you got a gender — but it means throwing away every signal that distinguishes an answer resting on 62,240 birth registrations from one resting on a reference list entry with no count behind it at all. Those two answers look identical if you only read gender. They should not be treated identically.
Here is what each field is for.
The response
{
"status": true,
"used_credits": 1,
"remaining_credits": 49999,
"expires": null,
"q": "Jordan",
"name": "Jordan",
"gender": "male",
"country": null,
"total_names": 62240,
"probability": 84,
"confidence": "high",
"duration": "1ms",
"source": "db",
"matched_as": null
}
gender
male, female, or null.
null does not mean "this person has no gender". It means we have no evidence, and returning it is a deliberate choice over guessing. There is an opt-in force parameter that returns the most likely gender even below the confidence threshold; it is off by default, because a coin flip presented as certain is worse than no answer.
probability
An integer from 50 to 100, or 0 when gender is null.
This is the single most misread field in the category, so precisely: it is the observed dominant-gender ratio in the underlying data, not a model confidence. When it says 84 for Jordan, that means 84% of the 62,240 recorded people named Jordan were male. It is not a claim about how sure a classifier feels.
The distinction matters because a ratio is only as meaningful as the count it was computed from — which is the next field.
total_names
How many observations the ratio was computed on. 0 means the source supplied no auditable count.
A probability of 100 on three observations and a probability of 97 on 41,000 are not comparable, and no single number can express the difference. That is why they are two fields.
confidence
Derived directly from total_names, with no judgement in between:
| Value | Condition |
|---|---|
unknown |
gender is null |
high |
100 or more observations |
medium |
25 to 99 observations |
low |
1 to 24 observations |
unverified |
0 observations — the source publishes no counts |
unverified is the interesting one. Our counted data comes from seven national statistics offices — the US SSA, the UK ONS, France's INSEE, StatCan, Spain's INE, Ireland's CSO and Norway's SSB. Everywhere else, coverage comes from WGND 2.0, which spans 195 countries and territories and carries no counts whatsoever.
So a name attested only in the countless data returns a probability capped at 95 and confidence: unverified. The answer may well be right. It is a different kind of claim: "a reference dataset lists this name as female here" rather than "we observed 40,000 of them".
You can see the seam in a single name. Andrea with country=IT correctly returns male, at probability 95 with total_names: 0 — Italy publishes no registration counts. The same name with no country returns female at probability 98 on 24,743 observations, because the German and American registrations dominate the global pool. Both are honest; only one is counted. That whole problem is covered in the names where the answer depends on the country.
source
Where the answer came from:
| Value | Meaning |
|---|---|
db |
Direct match in the name data |
script |
Non-Latin input bridged to a Latin entry — we transliterated |
fuzzy |
Approximate match to a nearby spelling; see matched_as |
llm |
Model fallback, only when you have opted in |
none |
No answer |
db and script carry different weight and the field exists so you can tell them apart. If source is script, the characters you sent were mapped to a Latin skeleton before lookup, and the mapping is one more place an error can enter.
matched_as
For a fuzzy match, the entry that was actually matched. null otherwise.
If you sent Katharina and matched_as says katarina, you now know the answer came from a neighbouring spelling rather than yours. Whether that is fine is your call — but you get to make it.
name
What was actually looked up after titles, initials and surnames were stripped.
Treat this as an audit field. It separates extraction failures from classification failures, which are two different bugs. If you sent Zhang Wei and name comes back Zhang, the surname got classified and the confidence: high on that row means nothing. Same for j.smith@example.com returning Smith. Both cases are worked through in the Chinese name post and the email extraction post.
The rest
q echoes your raw input unchanged. country is the country the statistics came from, or null for the global aggregate. duration is server-side processing time. expires is always null, because purchased credits do not expire. data_version identifies the data snapshot the answer came from — the first thing to ask about when a result changes between two runs.
Two answers that look the same and are not
| Field | Answer A | Answer B |
|---|---|---|
gender |
female | female |
probability |
95 | 100 |
total_names |
0 | 655 |
confidence |
unverified |
high |
source |
db |
db |
Read only the first row and these are the same answer. Read all five and A is an attestation while B is a measurement. If your pipeline writes both into the same column with no provenance, you have laundered one into the other.
Thresholds, by what the column is for
There is no universal cutoff. There is a cutoff per use case:
| Use | Rule |
|---|---|
| Marketing salutation | confidence in (high, medium) and probability >= 90 |
| Segmentation and reporting | accept everything including unverified; keep null as its own bucket and never impute it |
| Personalisation with a visible cost of being wrong | confidence: high and probability >= 95, with a manual review queue for the rest |
| Legal, medical or financial consequence | do not infer gender from a name |
The second row deserves a note. When you are counting rather than addressing, imputing the nulls is the mistake. The names that fail to resolve are not a random sample — they cluster by script and by country, as our coverage table shows in detail. Filling them in with the majority class does not remove the bias, it hides it inside your totals.
Why we expose all of this
Because the alternative is asking you to trust a single number, and this category has not earned that.
Every field above exists so that you can audit an answer without contacting us: see where it came from, see how much evidence was behind it, and decide for yourself whether that is enough for what you are about to do with it. The full field reference has the rest, and the gender API overview has the endpoints.
Every claim on this page is measurable against your own list. The free tier is enough to check it.
Related
-
How to compare name-to-gender APIs without trusting anyone's marketing
What to measure before you pick a vendor, why a single accuracy percentage tells you nothing, and how to run the same test on all of them — including us.
-
Our coverage, script by script — including where we fail
A reproducible benchmark across 4,610 names, 25 countries and nine writing systems. Two scripts return almost nothing, and we publish those numbers too.