LinkedIn Profile Search & Email to Name - No Cookies avatar

LinkedIn Profile Search & Email to Name - No Cookies

Pricing

Pay per usage

Go to Apify Store
LinkedIn Profile Search & Email to Name - No Cookies

LinkedIn Profile Search & Email to Name - No Cookies

Reverse-look up a work email to the right person: full name, job title, current company - or search LinkedIn people by keyword, company, location, school. Verified two-way match, blank instead of wrong. No login, no cookies. JSON, CSV, Excel.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Andrew Babo

Andrew Babo

Maintained by Community

Actor stats

0

Bookmarked

2.2K

Total users

1.1K

Monthly active users

11 days ago

Last modified

Share

LinkedIn Profile Search & Email to Name Lookup (No Cookies, No Login)

Turn a work email into a verified person — full name, job title and current company — or search LinkedIn people by keyword, company, location or school. No LinkedIn account, no cookies, no session sharing, no ban risk on your own profile.

Built for cold outreach, CRM enrichment and lead qualification teams who cannot afford to greet a stranger by the wrong name.


Table of contents


What this LinkedIn scraper does

ModeYou giveYou get
Reverse email lookupdylan.church@mintselection.comFull name, job title, current company, profile URL, location, photo
People searchhead of growth fintech, London, RevolutMatching public profiles with the full public profile data

Both modes read public LinkedIn pages only. Nothing here depends on a logged-in session, so there is nothing to get restricted, banned or rate-limited on your account — because there is no account.

The email mode is the reason this actor exists: most LinkedIn search actors take a name and a company and return a list of plausible people. This actor takes the one identifier you actually have after an email-verification pass — the address itself — and resolves it to a single verified identity, or tells you honestly that it cannot.


Benchmark: 25 real work emails (measured, not estimated)

Side-by-side against a leading LinkedIn profile search actor on the same 25 real work emails:

This actorA leading LinkedIn profile search actor
Correct person from email only19 / 250 / 25 (email input is not supported)
Correct person given name + companyn/a (not needed)14 / 25 top result
Wrong person returned07 / 25 (top result was a different human)
Total time for 25 emails47 seconds~16 seconds per single lookup
Cost per email~$0.003~$0.10 per search

The 6 remaining emails came back blank with a reason code — by design, not by failure.


Why "blank" beats "wrong"

Most email-to-name tools take the first search result with a similar name and attach it to your campaign. That is how "Hi Ruth" ends up in an email to John. This actor scores every candidate on two independent axes:

  • Name axis — does the name inside the email match the profile name? (first.last, flast, firstl, firstlast, initials…)
  • Company axis — does the email domain match the company the person actually works for? Confirmed on LinkedIn, and when LinkedIn hides the employer, on an external source such as the company team page or a press release.

Both must agree. If only one agrees, or two candidates tie, the row comes back empty with a machine-readable reason instead of a guess. Every blank row also carries rejectedCandidates, so you can audit the decision instead of trusting it.


Quick start

  1. Open the actor and paste one or more work emails into Emails.
  2. Leave Mode on full and set the proxy group to RESIDENTIAL (already the default).
  3. Press Start. Each email takes a few seconds; 25 emails at maxConcurrency: 25 finish in under a minute.
  4. Download the results as JSON, CSV or Excel from the Dataset tab, or pull them through the API.

Email mode, minimal:

{
"emails": ["dylan.church@mintselection.com"]
}

Keyword mode, minimal:

{
"search": "head of growth fintech",
"locations": ["London"],
"maxItems": 50
}

Input reference

FieldTypeDefaultDescription
emailsarray—Work emails to reverse-look up. Provide this or search, not both. Each entry is either a plain address ("jane@acme.com") or an object carrying its own company context: { "email": "jane@acme.com", "companyName": "Acme Group", "companyDomain": "acme.com" }. Per-entry hints win over the run-wide companyName / companyDomain, so a single run can cover thousands of addresses from different employers.
searchstring—Free-text people search query (e.g. "product manager fintech").
locationsstring[]—Narrow keyword search by location (e.g. ["London"]).
currentCompaniesstring[]—Narrow keyword search by current employer (e.g. ["Revolut"]).
schoolsstring[]—Narrow keyword search by school.
companyNamestring—Run-wide employer brand-name hint for email mode (e.g. "Emerald Carrying Company"). Used twice: to find extra candidates (an additional public search for "Name" "Company" linkedin when nothing found so far mentions that company) and to confirm a profile whose employer LinkedIn hides from guests. Useful when the email domain is an abbreviation of the company name. Overridden by a per-email hint.
companyDomainstring—Run-wide employer domain hint for email mode. When set, it replaces the domain derived from the email for company matching. Overridden by a per-email hint.
includeRawCandidatesbooleanfalseWhen on, every row also includes rawCandidates[] — the full pre-filter candidate list with scores, matched signals and rejection reasons, so you can apply your own acceptance rules.
maxItemsinteger100Maximum profiles returned in keyword mode.
modefast / fullfullfast returns identity fields only; full adds experience, education, summary, languages.
maxConcurrencyinteger8Parallel lookups. 25 is safe and the fastest tested setting.
maxRunTimeSecsinteger3600Hard stop for the whole run.
cacheTtlDaysinteger14Profiles are cached by slug; repeat lookups within the TTL are near-free. Set 0 to always fetch fresh.
proxyConfigurationobjectRESIDENTIALResidential proxies are strongly recommended (see FAQ).
sessionCookiesstring—Optional li_at cookie if you want to use your own session. Nothing depends on it.

Output reference

One dataset row per email (email mode) or per profile (keyword mode), exportable to JSON, CSV, Excel, XML or HTML and available through the Apify API.

FieldMeaning
emailThe input email (email mode)
matchedtrue only when both name and company axes confirm the same profile
confidence0–1 match score. On a blank row (matched: false) this is the score of the best candidate that was rejected, so you can see how close the row came
confidenceLabelhigh (≥ 0.8), medium (≥ 0.6) or low — always present, including on blank rows — pick your own acceptance threshold
matchedSignalsWhich verification signals fired, e.g. ["name-in-email", "domain-abbreviation"]
bestCandidateUrlBlank rows only: the profile that scored highest but was not published
reasonCodeMachine-readable decision (table below)
fullName, firstName, lastNameParsed name
headline, currentTitle, currentCompany, currentCompanyUrlCurrent role
titleSourceWhere the job title came from: profile (experience section), headline (profile top card), search-snippet (public search result line) or null when no title could be verified. Titles are never guessed. A headline that reads like a pitch ("Interested in mobile technology and e-Commerce.") is kept in headline and not promoted to currentTitle.
companySourceWhere the employer came from: profile, search-snippet, input-hint (the companyName you sent with the email, used only on a verified match) or null
companiesAll companies seen on the profile (current + past)
profileUrlCanonical LinkedIn profile URL
location, countryPublic location
photoUrl, followers, connectionsPublic profile metadata
summary, languages, experience[], education[]full mode only
dataQualityfull or partial (partial = LinkedIn served an obfuscated guest page)
rejectedCandidates[]Candidates that failed verification, each with confidence, confidenceLabel, nameScore, domainScore, matchedSignals and rejectedReason — for auditing blank rows and tuning your own threshold
rawCandidates[]Only when includeRawCandidates is on: the full pre-filter candidate list with per-candidate scores, matchedSignals, accepted flag and rejection reason
scrapedAtISO timestamp

Matched signals

matchedSignals tells you exactly which evidence confirmed the match:

SignalMeaning
name-in-emailThe email local part encodes the person's name (first.last, flast, …)
domain-websiteThe email domain matches the company website on the profile (strongest)
domain-company-nameThe domain matches the company name on the profile
domain-abbreviationThe domain is an abbreviation of the company name (emcarry ↔ Emerald Carrying Company, ms ↔ Mint Selection)
domain-past-companyThe domain matches a past employer (weaker)
domain-in-page-textThe company is masked, but the domain root appears in the visible profile text
company-name-hintYour companyName input matched the company on the profile
outside-sourceA page outside LinkedIn (company team page, press release) ties this person to the domain

Reason codes

reasonCodeMeaning
MATCHEDName and company both confirm the same profile
AMBIGUOUSTwo or more candidates are equally plausible
DOMAIN_MISMATCHName matches, but the person does not work at that domain
NAME_MISMATCHNothing with a matching name was found
NOT_FOUNDNo public profile surfaced at all
GENERIC_EMAILGmail/Outlook address — no company signal exists
ROLE_EMAILinfo@, sales@ — not a person
TIME_LIMITThe caller's run-time limit was reached; this row was saved before shutdown and can be retried

Example row

{
"email": "satya.nadella@microsoft.com",
"matched": true,
"confidence": 0.96,
"reasonCode": "MATCHED",
"fullName": "Satya Nadella",
"headline": "Chairman and CEO at Microsoft",
"currentCompany": "Microsoft",
"profileUrl": "https://www.linkedin.com/in/satyanadella"
}

Common recipes

Enrich a CRM export. Export your leads as a CSV with an email column, upload it in the input editor (the actor accepts pasted lists), run, then download the dataset as Excel and join it back on the email column.

Skip non-people cheaply. Role mailboxes (info@, sales@) and free-mail addresses are rejected before any network traffic, so a dirty list costs almost nothing to clean.

Verify a cached row is still current. Set cacheTtlDays: 0 to bypass the cache and re-read the profile — useful before a big send.

Audit a blank row. Open the row's rejectedCandidates: you will see every candidate that was considered, its name/company scores, and why it was rejected.

Call it from your own app. Use the Apify API or the JavaScript/Python client with call(); the dataset items map one-to-one to your input emails.


Use cases

  • Cold email personalisation — you have a verified email, you need the real name and title before you write the first line.
  • CRM enrichment — fill missing name, title, company fields on inbound leads.
  • Lead qualification — confirm the contact still works at the company on the email domain.
  • Recruiting — search candidates by keyword, company, location or school.
  • Data hygiene — flag role mailboxes and free-mail addresses before they enter a sequence.

Speed and cost

  • 25 emails in 47 seconds at maxConcurrency: 25.
  • ~$0.003 per email including proxy usage, measured on a real run.
  • Repeat lookups are close to free: profiles are cached by slug for cacheTtlDays (default 14).

How the matching works

  1. Parse the email. Role mailboxes and free-mail providers are rejected instantly. Personal emails yield candidate name patterns and a company domain.
  2. Discover candidates. Search engines surface public /in/ profile URLs for the name; a direct slug guess from the email pattern is tried in parallel.
  3. Read the public page. Structured data on the public profile gives name, headline, employer, location, experience and education.
  4. Score two axes. The name pattern must match the profile name, and the email domain must match the employer. If LinkedIn hides the employer on the guest page, the actor looks for an independent confirmation (company team page, press release) before deciding.
  5. Decide. Both axes agree → MATCHED. Anything else → blank row with a reason code and the rejected candidates attached.

Limits and honest caveats

  • Coverage depends on public visibility. Profiles with no public page, or pages LinkedIn heavily obfuscates for guest traffic, resolve to blank rather than to a guess. In the benchmark that was 6 of 25.
  • Very short API timeouts reduce coverage. The actor respects the run timeout imposed by the caller and saves unfinished emails with TIME_LIMIT before shutdown instead of letting the run end as TIMED-OUT. For reliable enrichment, allow at least 60 seconds; large batches should use the default.
  • Very common names (think john.smith@apple.com) may resolve to a real person with that exact name at that exact company who is still the wrong person. The two-axis check keeps this rare, but no public-data tool can eliminate it entirely.
  • No email extraction. Public profiles do not carry reliable email addresses, so this actor never invents them. It goes the other way: email in, identity out.

FAQ

Do I need a LinkedIn account or cookies? No. The actor reads public pages. An optional li_at field exists only if you want to use your own session — nothing depends on it.

Will it return email addresses? No. It goes the other way: email in, identity out.

Why did some rows come back empty? Because the two-way check did not pass. Read reasonCode and rejectedCandidates to see exactly why. An empty row is a deliberate answer, not a failure.

Which proxies should I use? Residential. LinkedIn serves partially hidden ("*****") guest pages to datacenter addresses; dataQuality reports partial when that happens, and the actor never publishes an obfuscated field as if it were text.

Is scraping public LinkedIn data legal? Publicly accessible pages are generally scrapable, but you are responsible for how you use the data, including GDPR/CCPA duties for personal data. This actor collects no private, logged-in-only data.

Can I run it on a schedule or from my own app? Yes — Apify Schedules, the API, or any of the JavaScript/Python clients.


For AI agents (MCP-ready)

This actor is designed to be called by AI agents, not just humans. It works out of the box with the Apify MCP Server — add it to Claude Desktop, Cursor or any MCP client and the agent can resolve emails and search people on its own:

{
"mcpServers": {
"linkedin-profile-search": {
"url": "https://mcp.apify.com/?actors=andrew_babo/linkedin-profile-search",
"headers": { "Authorization": "Bearer <YOUR_APIFY_TOKEN>" }
}
}
}

Agent skill (paste into your agent's instructions)

You can resolve work emails to verified people using the
"linkedin-profile-search" tool.
WHEN TO USE
- You have a work email and need the person's full name, job title,
current company and LinkedIn URL.
- You need to find people by job title / company / location / school.
HOW TO CALL
- Email lookup: { "emails": ["jane@acme.com"] }
Better accuracy with context:
{ "emails": [{ "email": "jane@acme.com", "companyName": "Acme Group" }] }
- People search: { "search": "head of growth fintech",
"currentCompanies": ["Revolut"], "locations": ["London"] }
OUTPUT CONTRACT
- matched: true → fullName, jobTitle, currentCompany, profileUrl are
verified on TWO independent axes (name pattern + company). Safe to use
in a cold email greeting.
- matched: false → do NOT guess or fill a name. Read reasonCode:
NO_CANDIDATE (no public profile found), NO_COMPANY_EVIDENCE (person
exists but employer could not be confirmed), ROLE_OR_FUNCTIONAL_EMAIL,
FREE_EMAIL_PROVIDER, BELOW_MIN_CONFIDENCE. Report the reason, move on.
- NEVER treat an empty row as an error. A blank row is a correct answer.
- dataQuality: "partial" means LinkedIn hid some fields from guest
traffic; hidden fields are never fabricated.
COST
- ~$0.003 per email, 25 emails in under a minute. Cache makes repeat
lookups nearly free for cacheTtlDays (default 14).