Skip to content
Finowl

Gender prediction

Gender from email addresses: what works and what doesn't

How gender prediction from email addresses finds a name in the local part, why firstname.lastname@ works but info@ doesn't, and how to handle unknowns.

Sometimes an email address is the only thing you have about a contact. Newsletter signups, trial forms and imported lead lists often have no name field at all. Predicting gender from the email address can still work, but only when the address actually contains a name. This post explains how a name is found in an email, which address patterns work, which never will, and how to handle the gaps responsibly.

How a name is found in an email address

An email address has two parts: the local part before the @ and the domain after it. Personal names live in the local part. In jane.smith@example.com, the local part is jane.smith, and the given name is jane.

When you call Finowl's email endpoint, it looks for a name candidate in the local part, then predicts from that name the same way a name lookup does.

bash
curl -X POST https://api.finowl.co/v1/gender/email \
  -H "Authorization: Bearer $FINOWL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "jane.smith@example.com" }'
json
{
  "data": {
    "result_status": "identified",
    "gender": "female",
    "confidence": 0.98,
    "confidence_kind": "observed_frequency",
    "sample_count": 2570,
    "name": "jane",
    "country": null,
    "source": "dataset",
    "reason": null
  }
}

The most useful field for email lookups is name. It shows exactly which name was found in the address. If a result surprises you, check name first: the issue is usually which part of the address was treated as the name, not the prediction itself.

Separators help

Dots, underscores and hyphens make the structure of a local part obvious. jane.smith, jane_smith and jane-smith all clearly start with a given name. Addresses that run words together, such as janesmith, are harder, and addresses that start with an initial, such as jsmith, may not contain a usable given name at all.

Patterns that work

These address styles usually contain a clear given name:

Pattern Example Why it works
first.last maria.garcia@example.com Given name is first and separated
first_last or first-last tom_baker@example.com Same structure, different separator
first only priya@example.com The whole local part is a name
first + digits daniel1987@example.com Digits are easy to set aside

These are common in personal accounts and in companies that use a firstname.lastname@ convention, which makes B2B contact lists a good fit as long as the addresses belong to individuals.

Patterns that don't work

Some addresses do not contain a person's name, and no amount of processing will change that.

Role and shared addresses

info@, sales@, support@, hello@, admin@, billing@, team@ and similar addresses belong to a function, not a person. Several people may read them. There is no individual gender to estimate, and you should not try.

Random and generated strings

Addresses like x7k2q9@example.com, or the relay addresses that some email privacy features generate, are designed not to reveal anything. They will come back unknown.

Initials and surname-first formats

jsmith@, smith.j@ and js@ usually lack a full given name. Some surname-first formats can produce a misleading match when a surname also happens to be a given name. The returned name field lets you catch these cases.

Words that happen to look like names

A local part like rose.gardens or april.promo may contain a word that is also a first name. Treat results from obviously non-personal addresses with suspicion, and filter them out before you send them.

Filter before you send

An unknown result is a normal, successful lookup, and it is charged like any other. So it pays to skip addresses that cannot produce a useful answer. A simple pre-filter in JavaScript:

javascript
const ROLE_PREFIXES = new Set([
  "info", "sales", "support", "hello", "admin", "billing", "contact",
  "team", "office", "help", "noreply", "no-reply", "marketing", "jobs",
]);

function worthPredicting(email) {
  const local = email.split("@")[0].toLowerCase();
  if (ROLE_PREFIXES.has(local)) return false;
  if (!/[a-z]{3,}/.test(local)) return false; // no run of letters
  return true;
}

async function genderFromEmail(email) {
  if (!worthPredicting(email)) return null;

  const res = await fetch("https://api.finowl.co/v1/gender/email", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.FINOWL_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ email }),
  });
  if (!res.ok) return null;

  const { data } = await res.json();
  return data.result_status === "identified" ? data : null;
}

Adjust the list to your data. If you see a lot of no_name_candidate results for a particular prefix, add it.

Prefer a name when you have one

If a contact record has both a name and an email, predict from the name. A name field is usually a direct statement from the person, while an email local part is an indirect clue. Use the email endpoint as a fallback for records where the name is missing.

In a batch, you can mix types per item, so a single request can cover both cases:

json
{
  "items": [
    { "id": "c1", "type": "name", "value": "Maria Garcia", "country": "ES" },
    { "id": "c2", "type": "email", "value": "tom_baker@example.com" }
  ]
}

Send that body to POST /v1/gender/batch. Each row in the response has its own charged_credits, and a 200 response can still contain per-item error objects, so check every row.

Handling unknown results

Expect a share of email lookups to come back unknown. The response has result_status: "unknown", gender: null and a reason:

  • no_name_candidate: nothing in the local part looked like a name. This is the most common reason for role addresses and random strings.
  • not_found: a candidate was found, but there is no usable data for it.
  • ambiguous: the name is used for more than one gender without a clear lean.
  • insufficient_evidence: there is some data, but not enough to be confident.

Your product should treat unknown as a first-class outcome. For personalization, fall back to neutral wording. For analytics, report unknowns as their own category rather than dropping them, so your totals stay honest. The interpreting predictions guide has more on thresholds, and confidence scores and unknown results goes deeper on picking a cutoff.

Privacy notes

An email address is personal data, and a gender estimate derived from it is also personal data. Handle both with care.

  • Tell people. Mention gender lookups in your privacy notice, including that you derive estimates from contact details.
  • Send only what you need. The email endpoint needs the address and nothing else. Do not attach extra profile data to the request.
  • Store the minimum. If you only need aggregate numbers, consider storing the aggregate rather than a per-person estimate.
  • Respect corrections. If a person tells you their gender, that always overrides the prediction, and you should not re-predict over it.

The data privacy docs explain how Finowl handles the data you send.

Responsible use

Gender prediction from an email address inherits all the limits of prediction from a name, plus extra uncertainty from extracting the name. It is a statistical estimate of how a name is typically used, not how a person identifies, and it will be wrong for some people.

  • Use it for aggregate analytics and low-stakes personalization only.
  • Never use it for eligibility, pricing, access or any decision with significant effects.
  • Let people state or correct their own gender.

For a full walkthrough of the underlying mechanics, read how gender prediction from names works. API details are on the gender API page.

Frequently asked questions

Which part of the email address is used?

The local part, before the @. Finowl looks for a name candidate there and returns it in the name field so you can see what was matched.

Why did info@ or sales@ come back unknown?

Role addresses belong to a function, not a person, so there is no name to find. They typically come back with reason: "no_name_candidate". Filter them out before sending to avoid spending credits.

Am I charged when an email has no name in it?

Yes. An unknown result is a successful lookup and costs 1 credit like any other. Requests rejected before running, such as a 400 for invalid input, are free.

Should I use the email endpoint if I have the person's name?

Use the name endpoint instead. A name field is a more direct signal than an email local part, and you can still fall back to the email endpoint for records without a name.

All articles