Email Finder API — FetchLayer Docs
Documentation menu
FetchLayer FetchLayer API

Email Finder API v1

One target in, one graded answer out, from https://api.fetchlayer.dev/email-finder. A website, a social profile or a YouTube channel — and an answer either way, including the answer that there is nothing to find.

OpenAPI JSON

“No email” is an answer, not a failure

status: "NO_EMAIL_LISTED" comes back as a 200. It means the search ran and the target publishes no readable contact address — and for large companies that is the ordinary outcome, not an edge case. Measured on 17 September 2026: github.com, g2.com and ticketmaster.com all answered this way, each with a note naming what was examined. Stripe publishes a support portal rather than an address.

The failure case has its own status. A target that could not be read at all is a 503: {"error":"the target could not be read right now, please retry"}indeed.com returned one in 6.2s, and a domain that does not resolve in 2.8s.

That separation is the whole point. Retry the 503; take the 200. A negative result you can rely on is what lets you close a row out instead of re-running it forever.

Confidence is graded on who published it

An address the target published on its own pages can grade high. An address found anywhere else cannot — however right the domain looks.

Target Address Published by Grade
python.orgpsf@python.orgits own /about pagehigh
stripe.com…@stripe.comsomewhere else on the webmedium
x.com/navalan address on a third party’s sitesomewhere else on the weblow

The stripe.com row is the rule working, not a bug: the address really is @stripe.com, and it still grades medium because Stripe did not publish it where it was found.

The rule exists because a plausible address on a perfect domain can belong to nobody. A lookup once returned jane.diaz@stripe.com at high confidence — Stripe’s own fictional demo persona from their checkout examples. Grading on who published it rather than on what it ends in is what rules that class of answer out.

Every response carries sourceUrl, so a grade is never something you have to take on faith.

One nuance in onTargetDomain: it is measured against the target as you gave it. For a YouTube channel that host is youtube.com, so an address published on the creator’s own website reads false@veritasium returned veritasium@gmail.com found on veritasium.com, graded low. That is correct; sourceUrl is what tells you it is nonetheless a good address.

Available endpoints

Whole, partial, or failed — the response says which

searched[] lists what was examined, incomplete[] lists anything that could not be finished, and complete summarises the two. Read complete rather than inferring wholeness from how long a call took.

Websites and YouTube channels are the strong inputs — every one measured returned a complete answer. Social profiles are supported, can take longer, and may return a partial result, which the response marks as incomplete. The one partial observed was https://x.com/paulg: a 200, complete: false, incomplete: ["web-search"], with a note saying so and that retrying may cover more.

How long a lookup takes

Between about 10 and 100 seconds for a 200, measured across websites, X profiles and YouTube channels on 17 September 2026 — websites 9.5–101.6s, YouTube 50.9–77.6s, social 19.6–95.8s. It is driven by how much there is to look through for a given target rather than by the kind of target, so it does not sort neatly by input type.

Budget timeouts against the top of that range, and run lookups in the background rather than inside a request/response cycle.

Billing

One credit per completed lookup — including a NO_EMAIL_LISTED. The search is the work, and it is identical either way. What you are buying is a definitive answer about a target, not a lottery ticket on one; a “no” you can rely on is the result that lets you stop working a row.

Every completed lookup reports pagesFetched: 1. /resolve-target reports 0 and is free. A 503 fetched nothing.

pagesCrawled is not a price. It ranged from 1 to 65 across the targets measured, and it is there so two targets that both cost one credit are not indistinguishable when one answered immediately and the other did not.

Errors

  • 400 — the request is wrong, and the message names the field: “target: Invalid input: expected string, received undefined” for a missing target, “Unrecognized key: …” for an unknown one. The body is a strict object, so a typo is rejected rather than ignored.
  • 401 — missing or invalid key.
  • 503 — the target could not be read. This is the one to retry. A target that publishes nothing is a 200, not this.