Blog/Sales & enrichment
11 min read

Hunter.io API: Domain Search Finds, Email Finder Guesses

Hunter.io domain search returned ten verified addresses at confidence 85. Email finder returned one address at confidence 16 with no source. Same provider.

Hunter.io API: Domain Search Finds, Email Finder Guesses

Copy this line to your agent to list the email addresses found at a company domain.

set up https://monid.ai/SKILL.md and use hunterio /domain-search for a domain

On 2026-09-14 we pointed two Hunter.io endpoints at the same domain. Domain search returned ten addresses, each with a source, a verified status and a confidence of 85. Email finder, asked for the company's cofounder, returned one address with a confidence of 16, no source and no verification. Both are Hunter.io. Only one of them found anything. This guide runs through Monid, the OpenRouter for agent tools.

What does Hunter.io domain search actually return?

Every address the provider has observed at a domain, with the evidence attached to each one, plus a description of the domain's mail setup that decides how much the rest can be trusted.

The domain block

hunterio/domain-search for stripe.com, limit 10, on 2026-09-14:

{
  "domain": "stripe.com",
  "disposable": false,
  "webmail": false,
  "accept_all": true,
  "pattern": "{first}",
  "organization": "Stripe",
  "linked_domains": [ "..." ],
  "emails": [ "..." ]
}

Three of those fields matter before you read a single address. webmail: false says this is a company domain rather than a free-mail provider. pattern: "{first}" is the provider's inference about how the company forms addresses. And accept_all: true is the one to stop on, covered in the next section.

The address rows

Ten rows, and every one of them looked like this:

{
  "value": "sudheer@stripe.com",
  "type": "personal",
  "confidence": 85,
  "first_name": "Sudheer", "last_name": "Anne",
  "position": "Head of Engineering",
  "sources": [ { "domain": "...", "uri": "...", "extracted_on": "..." } ],
  "verification": { "date": "...", "status": "valid" }
}

Confidence 85 on all ten. One source on all ten. Verification valid on all ten. The uniformity is worth noticing: these are addresses the provider found published somewhere, and the confidence reflects that each was seen once in the wild rather than generated.

What the ten rows were

Heads of Engineering, Growth, Marketing, Sales Strategy, Governance, Program Management, Commercial Operations, a Director of Go-To-Market, a Content Design Lead and an Operations Associate. Senior-skewed, which is what you would expect from addresses that appear on public pages: the people who speak at events and sign blog posts are the ones whose addresses leak.

Domain search tells you who is findable, not who works there. The population is people with a public footprint, and it under-represents everyone else.

📖 See also Extracting Leadership Contact Information Without Paying to Look

Why did email finder return a confidence of 16?

Because it did not find anything. It generated an address from the domain's pattern and reported honestly how little that is worth.

The call and the answer

hunterio/email-finder for first name Patrick, last name Collison, domain stripe.com:

{
  "email": "pcollison@stripe.com",
  "score": 16,
  "source_type": "generated",
  "sources": [],
  "verification": { "date": null, "status": null },
  "accept_all": true,
  "position": "Cofounder",
  "company": "Stripe",
  "linkedin_url": null, "twitter": null, "phone_number": null
}

Read the four fields together. source_type: "generated" says the address was constructed, not observed. sources: [] confirms nobody has ever published it. verification.status: null says it was not checked. score: 16 is the provider's own estimate that this string is a working mailbox, and it is saying one in six.

Why the pattern did not help

The domain block said pattern: "{first}", meaning Stripe addresses are typically first-name-only. The finder returned pcollison@, which is first-initial-plus-last. It did not follow its own inferred pattern, presumably because patrick@stripe.com is already known to belong to someone else. The finder had a conflict and picked a fallback shape, and the score reflects that.

What this is not

It is not a broken endpoint. Email finder is doing exactly what an email finder does: taking a name and a domain and producing the most likely address. On a person whose address has never appeared publicly, "most likely" is a pattern guess, and the endpoint is unusually honest about that through its score and its source_type.

The failure would be treating the result as a find. Store pcollison@stripe.com in a CRM next to sudheer@stripe.com and they look the same. One was observed and verified; the other is a one-in-six guess. The fields that separate them are score, source_type and sources, and they are the first three columns a flattening step drops.

How do you use Hunter.io through one key?

Three steps. Discovery is free, and the first paid step is the one that finds things.

For agents

Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:

set up https://monid.ai/SKILL.md

It learns the whole discover, inspect, run workflow itself. More in the agent quickstart.

For humans

npm install -g @monid-ai/cli
monid keys add -k <your-api-key> -l main

Step 1. Search the domain first

What it does. Lists every observed address at a company with sources and verification.

The endpoints. hunterio/domain-search, billed per result, takes domain or company in the body.

The call.

monid run -p hunterio -e /domain-search -i '{"domain": "stripe.com", "limit": 10}'

Note -i, the body flag. The endpoint schema on the day of writing listed these as query parameters and the provider rejected them there with a 400 naming the fix: "Provide at least one of domain or company." Body works.

What comes back. The domain block and up to limit address rows.

What it costs. A few cents per address returned, so limit is the budget. Current figures at monid.ai/tools.

Step 2. Look up the ones you have an address for

What it does. Turns an address into a person and their company.

The endpoints. hunterio/combined/find, per call, requires email.

The call.

monid run -p hunterio -e /combined/find --query '{"email": "patrick@stripe.com"}'

What comes back. A person record with a fuzzy flag and a company record. On 2026-09-14 this address resolved to an IT administrator, not the cofounder, and that is covered in the reverse email lookup guide.

Step 3. Generate only as a last resort, and store the score

What it does. Guesses an address for a named person when nothing was observed.

The endpoints. hunterio/email-finder, per result, takes domain, first_name, last_name.

The call.

monid run -p hunterio -e /email-finder \
  --query '{"domain": "stripe.com", "first_name": "Patrick", "last_name": "Collison"}'

What comes back. One address, a score, a source_type and a sources array. Keep all three.

Give this to your agent

$Set up https://monid.ai/SKILL.md, and then use Monid to run a domain search on this company, then for each person on my list who is not in the results run an email finder, and flag every row where source_type is generated or score is under 60.

📖 See also Enriching a List When All You Have Is Email Addresses

Which score is safe to send to?

None of them on an accept_all domain without a separate check, and that is the field that decides it, not the score.

What accept_all means

Stripe's mail server accepts delivery for every address at the domain, real or not. That is a deliberate configuration many companies use. It means an SMTP-level verification cannot tell a live mailbox from a made-up one, because both get accepted.

That is why verification.status was valid on the ten observed addresses and null on the generated one. The observed ones are "valid" because they were seen published, not because a server confirmed them. The generated one has no status because there is nothing a verifier could learn.

The rule this produces

On an accept_all: true domain, treat verification as unavailable and lean on provenance instead:

def sendable(row, domain):
    if row["source_type"] == "generated": return False
    if not row["sources"]:                return False
    if domain["accept_all"]:              return row["confidence"] >= 80
    return row["verification"]["status"] == "valid"

On a domain that is not accept-all, the verification status is meaningful and you can use it. On one that is, only an observed address with a high confidence is worth a send, and a generated one is a bounce waiting to happen. The wider argument about bounces and sender reputation is in bounce rates and spam traps, and the cheapest place to enforce the rule is at the point an address enters your list, which is what verifying an email before it hits your list walks through.

Why the score alone misleads

A score of 85 on an observed address and a score of 16 on a generated one look like a scale, and they are two different measurements. The first is "how confident are we this published address is current". The second is "how likely is it this pattern-guess exists at all". Comparing them on one axis is comparing a fact's freshness to a guess's plausibility. source_type is the field that tells you which scale you are on.

Which endpoint should I use for which job?

EndpointWhat it doesInputOutputBest forBilling
hunterio/domain-searchObserved addresses at a companydomain or company, bodyAddress rows with sources and verificationBuilding a contact list from a domainPer result
hunterio/combined/findPerson plus company from an addressemailPerson record with fuzzy, company recordReverse lookupPer call
hunterio/email-finderGuess an address from a namedomain, first_name, last_nameOne address with score, source_typeLast resort, with the score storedPer result
hunterio/companies/findCompany profile from a domaindomainFirmographicsCompany-only enrichmentPer call
hunterio/discoverCompanies by attributeFiltersCompany listBuilding the target listPer call

Every row was verified with monid inspect on 2026-09-14. The table gives billing shape rather than figures, because shape drives design and current numbers live on monid.ai/tools.

The order of the first three rows is the order to call them in. Search returns what exists. Lookup enriches what you have. Finder guesses what neither found, and it should run last and be labelled.

When is Hunter.io the wrong tool?

Four cases.

You need the whole company, not the findable part. Domain search returns published addresses, which skews senior and public-facing. For a full org chart or a list of individual contributors, a people-search endpoint filtered on title and company is the right shape; the measured comparison is in the provider comparison.

Your target domains are accept-all. Verification is neutralised, the finder's guesses cannot be checked, and your only defence is provenance. If most of your list is large companies with permissive mail servers, budget for a second-source check rather than trusting any score.

You are looking up private individuals. Hunter.io's data is professional addresses observed on the public web. It is not a people-search product and it is not a route to a personal mailbox, and using it as one is both unreliable and a different legal question.

You want the platform. Hunter.io sells a UI with campaigns, sequences, a Chrome extension and team seats. We ship the API behind one key. If the person doing the work is not writing code, the platform is the right purchase and this is not a substitute.

And the disclosure: this is Monid's blog and we resell these endpoints, so the comparison here is between two things we sell, not between us and a competitor. The recommendation to run the finder last and label its output is a recommendation to spend less on it.

Conclusion

Hunter.io is two different products under one name. Domain search is a lookup over addresses the provider has seen, and every row it returned carried a source and a verification. Email finder is a generator over a domain's naming pattern, and the one row it returned said so in three separate fields: source_type: generated, sources: [], score: 16. Both answered honestly. Only one found anything.

The thing that matters more than the endpoint choice is accept_all. On a domain that accepts every address, verification tells you nothing and the score on a generated address is the only signal you have, and it said one in six. Keep source_type and sources next to every address you store, because without them an observed mailbox and a pattern guess are indistinguishable in a CRM.

Free next step: run monid inspect -p hunterio -e /domain-search to see the schema, then search one domain you know well and compare who came back against who you know works there. The gap is the population this data cannot see. Start at monid.ai.

FAQ

Is Hunter.io free?

Hunter.io offers a free plan with a small monthly allowance of searches and verifications, and paid plans above it priced by monthly volume. Through Monid the same endpoints are metered per call or per result with no plan, so a hundred domain-search rows costs a few dollars and there is no allowance to exhaust or tier to upgrade. Which is cheaper depends entirely on your volume shape: steady daily use favours a plan, bursty or occasional use favours metering. Current figures are on monid.ai/tools.

What does accept_all mean and why does it matter?

It means the domain's mail server accepts delivery for any address, whether or not a mailbox exists, so a verification check cannot distinguish real from invented. Many large companies run this way to avoid leaking which addresses are valid. On such a domain the verification.status field is not meaningful, generated addresses cannot be checked, and the only trustworthy rows are observed ones with a source. Read this flag before reading any score on the domain.

Hunter.io vs Apollo for finding emails: which is better?

They are different shapes. Hunter.io's strength is addresses observed on the public web, with provenance attached, which makes it strong on people who have a footprint and thin on everyone else. Apollo's people search is a database queried by title and company, which finds people regardless of footprint but reports its own confidence rather than a source URL. For a senior contact at a known company, run both and compare; for a full list of a function at a company, the database search is the right shape. The measured Apollo comparison is in the provider comparison.

Can I run domain search across a thousand domains?

Yes, one call per domain, and the cost is set by limit times domains because billing is per address returned. Set limit deliberately: ten addresses per domain answers "who is findable here" and a hundred answers "everyone findable here" at ten times the cost. Rate limits are enforced by the provider and surfaced through Monid as errors rather than silent truncation, so a batch that runs too fast fails loudly. Read the domain block first and skip accept_all domains that you cannot verify anyway.

Last updated September 2026.

hunter.iohunter io apiemail finderdomain searchemail verification