Reverse Email Lookup | Email to LinkedIn Profile
Pricing
from $7.70 / 1,000 person delivereds
Reverse Email Lookup | Email to LinkedIn Profile
Reverse email lookup to LinkedIn: give email addresses, get one person row per address with name, title, company, location and profile URL. Free plan: 100 emails per run. Pay per person delivered, no match free. Does not verify or find emails. No login or cookies.
Pricing
from $7.70 / 1,000 person delivereds
Rating
0.0
(0)
Developer
Open Enrich
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
5 days ago
Last modified
Categories
Features
Share
Reverse email lookup to LinkedIn: give a list of email addresses, get one row per address that matches a person, with name, title, current company, location and LinkedIn profile URL. No login, no cookies, no start fee. You pay only for a person row you receive: an address with nobody on file is free.
No login | Bulk list in one run | One person per email | Misses and ambiguous matches are free | JSON/CSV export | Works via API, MCP and schedules
Email in, person out. Many reverse-lookup tools take one address per run and bill the empty answers too. This one takes a list, looks each address up once and charges only for a person it can stand behind. When several people share an address and the best guess does not fit the address, the row is withheld and costs nothing. It does not verify that an address is deliverable and it does not find emails: for that use email-verifier and email-finder.
💳 Pricing and plans
One event, person, charged once per person row delivered. Prices per 1,000 people (set on the Pricing tab):
| Event | When it is charged | Free plan | Gold plan |
|---|---|---|---|
person | A person row is delivered to your dataset | $9.996 | $7.696 |
Bronze and Silver prices are on the Pricing tab. Higher Apify plans only lower the price. Empty runs, emails with nobody on file, ambiguous matches, entries that are not emails, failed lookups and notices are free, and there is no start fee.
Plan-credit math. The free plan's $5 monthly credit covers about 500 people at the Free price.
Success-only billing
You are charged only for a person row you receive. An address with nobody on file gets one free notice row (reason: "not_found"). An address that matched several people, where the best candidate does not fit the address, gets one free notice row (reason: "ambiguous_match"). A match without a profile URL gets a free no_profile_url notice. An entry that is not an email, a repeat, or a lookup that fails is listed in MISSES with its position and a reason and costs nothing.
The free plan
Free Apify accounts get up to 100 emails looked up per run, and as many runs as their Apify credit covers. Nothing is stored on our side. When a list is longer, the first 100 valid emails are looked up and one free notice row (reason: "free_plan_limit") says how many were not looked up; they are not charged. Run again with the rest, or use a paid Apify plan for no per-run limit.
⚡ Why this reverse email lookup actor?
- A list, not one address. Up to 3,000 addresses per run, de-duplicated, each looked up once.
- Paste addresses as you have them.
jane@stripe.com,Jane Doe <jane@stripe.com>andmailto:jane@stripe.comall becomejane@stripe.com. - Withholds guesses it cannot back. If an address belongs to several profiles, a row is delivered and charged only when the address domain names the person's current employer and the part before the @ fits the name. Everything else is a free notice.
- Flat, readable rows. Name, title, company, location, years in role, profile URL. No nested raw profile.
- Success-only, no start fee. No match, bad entries, repeats and notices are free.
🎯 Use cases: find the person behind an email
- CRM clean-up. Put a name, title and company on contacts you only hold an address for.
- Inbound lead enrichment. A form fill or a newsletter signup becomes a profile you can research.
- Outreach research. Check who an address belongs to before you write.
- Agent workflows. An AI agent holds an address and needs the person and the profile in a single call.
🚀 Quick start: reverse email lookup
1. One address
{ "items": ["jane@stripe.com"], "limit": 1 }
2. A list
{ "items": ["jane@stripe.com", "Bob Smith <bob@acme.io>", "mailto:zed@foo.org"], "limit": 100 }
Each entry becomes a bare lower-case address before the lookup.
⚙️ Inputs
| Key | Type | Default | What it does |
|---|---|---|---|
items | array of strings | required | Email addresses. A name, a domain or a profile URL is not an email and is listed in MISSES as invalid_email. The same address written twice is looked up once. Maximum 3,000. Free plan: 100 emails per run. |
limit | integer | 100 | Most people delivered in the whole run, which also caps what is charged. Maximum 3,000. Emails not reached are listed in MISSES. |
includeAudit | boolean | false | Adds an audit object to each row. |
Any other field stops the run before a lookup with remove unsupported fields: .... Nothing is charged.
📤 Output
One result row per matched email, in input order. Empty values are left out.
| Key | Type | Meaning, and when it is missing |
|---|---|---|
email | string | The address you gave, cleaned |
fullName, firstName, lastName | string | The person's name |
headline | string | The profile headline. Missing when the person has none |
jobTitle | string | Current job title. Missing when the profile lists none |
company | string | Current employer, from the profile's open position. Missing when none is listed |
location | string | Place on the profile |
country | string | Two-letter country code |
startYear | integer | Year the current position started. Missing when not on file |
tenureYears | number | Years in the current position as the data holds it. Missing when not on file |
totalExperienceYears | number | Years of work experience as the data holds it. Missing when not on file |
connections | integer | Connection count on the profile |
profileUrl | string | Public LinkedIn profile URL. A row without one is never delivered |
slug | string | Profile slug |
updatedAt | string | When the profile was last refreshed in the data |
audit | object | Only with includeAudit: requestId, latencyMs, candidates, inputRaw |
Example output (the shape is real, the values are illustrative):
{"email": "ann@example.com","fullName": "Ann Example","firstName": "Ann","lastName": "Example","headline": "Engineering leader at Example","jobTitle": "VP Engineering","company": "Example","location": "Dublin, Ireland","country": "IE","startYear": 2022,"tenureYears": 4,"totalExperienceYears": 15,"connections": 812,"profileUrl": "https://www.linkedin.com/in/ann-example","slug": "ann-example","updatedAt": "2026-03-19 16:19:30.035Z"}
How to read the rows
- Work addresses match more often than personal ones. An address on a company domain (
ann@example.com) resolves more often than a personal mailbox (gmail.com,outlook.com). Coverage of personal addresses is lower, and a personal address says little about who the person is, so check the name before you act on it. - One address, one person. When the address belongs to a single profile, that profile is the row. We cannot prove that the person still uses the address.
- Shared addresses. Some addresses match several profiles (a common first name at a large company, a shared mailbox). The data then picks one. We deliver that pick only when the address domain names the person's current employer and the part before the @ fits the name. Otherwise you get a free
ambiguous_matchnotice.includeAuditshowscandidates, the number of people that shared the address. A delivered row can still be a namesake: for a short address likepat@bigcompany.com, confirm with the headline and title. - Company is the current open position. A person with several open positions gets the one that started last.
- No seniority level and no company domain. The data returns the employer's name, not its domain, and no seniority bucket, so neither is in the row.
Other records in the run
MISSES(key-value store):[{index, input, reason}]for every entry without a result row. Reasons:not_found,ambiguous_match,no_profile_url,invalid_email,duplicate_input(the same address as an earlier entry;duplicateOfnames it),not_looked_up_limit(the runlimitwas reached first),not_looked_up_error(the service failed three times in a row) orUpstream HTTP <code>.errors-person-by-email(key-value store): the lookups that failed for a technical reason, so you can re-run only those emails.RUN_SUMMARY: counts (requested, valid, looked up, found, not found, ambiguous, delivered).- Notice rows (
type: "notice") appear for an address with no person, an ambiguous match, a free-plan list longer than 100 (free_plan_limit), a reachedlimit(limit_reached), a reached spend limit (charge_limit_reached), repeated service failures (upstream_errors) or invalid input (invalid-input). Notices are never charged.
What is NOT returned
- Email addresses, phone numbers or deliverability checks (use email-finder and email-verifier)
- Work history, skills or education (use linkedin-profile-by-url)
- Gender, birth date or other private details
🛡️ Reliable results
Our data promise. We work to keep the data current, and we stand behind it. If a person has moved on, an address points at the wrong person or a row looks wrong, open the Issues tab with your run link. We review every report and sort it out with you, case by case.
- No match is free and visible. Every address without a row is in
MISSESwith its position and a reason and is never charged. - Repeats are looked up and charged once. The same address written twice is one row.
- Each row is saved as it is delivered. A run that stops keeps what it already produced.
- Bounded pace. Lookups run at about 60 a minute, so a long list takes time. The run timeout is one hour.
- Typos fail early. An unsupported input field, a limit above its maximum or a list above 3,000 stops the run before any charge.
🤖 For AI agents (MCP)
This actor runs through the Apify MCP server. Prompt to copy:
"Use b2bdata/person-by-email with items=["jane@stripe.com"] and limit=1. Return fullName, jobTitle, company and profileUrl."
When to use it. You hold an email address and need the person behind it.
When not to. You need to know whether an address is deliverable (use b2bdata/email-verifier), want to find an address from a name (use b2bdata/email-finder) or need a full profile (use b2bdata/linkedin-profile-by-url).
Input contract. items array of email addresses (maximum 3,000); optional limit 1-3,000 (default 100) and includeAudit.
Output contract. One row per matched email with email, fullName, jobTitle, company, profileUrl. Output is deterministic and schema-stable. Addresses without a match are a free notice row and listed in MISSES.
Smoke test. limit: 1 on a work address of a well-known company returns one row.
Error cases. No valid email addresses means no entry was an email. remove unsupported fields, a bad number or a list above 3,000 ends the run SUCCEEDED with one free invalid-input notice row and nothing charged.
🔌 Integrations: send results anywhere
- API. Fetch rows from the run's default dataset:
GET /v2/datasets/{datasetId}/items?format=csv. - Webhook on run success to push rows to your own endpoint.
- n8n, Make, Zapier. Use the native Apify nodes: run the actor, then read the dataset.
- Google Sheets, Airtable, HubSpot, Salesforce, Clay. Join on
emailand mapfullName,jobTitle,companyandprofileUrlto contact fields.
🕐 Schedule examples
- Nightly enrichment. A schedule with a saved task that points at the day's new contacts.
- Signup enrichment. A webhook from your form tool starts a run with the new addresses.
🔗 Related actors
b2bdata/email-finder: a work email for a person at a domain. Openb2bdata/email-verifier: whether an address is valid, catch-all or invalid. Openb2bdata/linkedin-profile-by-url: the full profile for a LinkedIn URL. Openb2bdata/social-handles-finder: social profiles from an email or LinkedIn URL. Open
❓ FAQ
Data and coverage
How do I find a LinkedIn profile from an email address?
Put the address in items and run. You get one row with name, title, company, location and profileUrl.
Does it work with personal email addresses? Sometimes. Personal mailboxes match less often than work addresses, and the person behind a personal address is harder to confirm. Work addresses on a company domain are the strong case.
Why did I get no row for an address?
It is in MISSES with a reason: nobody on file, an ambiguous match we did not stand behind, a match without a profile URL, or an entry that was not an email.
Is the person always the right one?
When an address resolves to a single profile, yes as far as the data goes. When several people share it, we deliver only a pick that fits the employer and the name, and includeAudit shows how many candidates there were. Confirm short or generic addresses with the title and headline.
Do I get email addresses or phone numbers back?
No. You get the person and the profile. Use b2bdata/email-finder to find an address.
Do I need a LinkedIn account or cookies? No. It is a lookup without login, cookies or an account to ban.
Pricing
What do I pay when an address has no match? Nothing. There is no start fee, and no match, bad entries, repeats and notices are free.
🛟 Support
Use the Issues tab on this actor's Apify page for bugs, questions and feature requests. We answer within 48 hours on working days. Please include the run ID and the input you used. Published on Apify by b2bdata. Not affiliated with, endorsed by, or sponsored by any company or person named in the examples above.