# Email to LinkedIn Profile Scraper (`khadinakbar/email-to-linkedin-profile-scraper`) Actor

Look up public LinkedIn profiles from email addresses: name, headline, profile URL, company, and location. Provider-backed via ScrapeCreators and SociaVault Google Search with optional public-profile enrichment. Cookieless, no LinkedIn login. MCP-ready.

- **URL**: https://apify.com/khadinakbar/email-to-linkedin-profile-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Lead generation, Social media, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $25.00 / 1,000 linkedin profile founds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Email to LinkedIn Profile Scraper

Turn one or more email addresses into public LinkedIn profiles. Paste a work email such as `satya.nadella@microsoft.com` and get one dataset row with `matchStatus`, profile URL, name, headline, company, and location when a public match exists. Unmatched or role-mailbox addresses return a free CLEAR row so you can tell a completed empty lookup from a provider outage. No LinkedIn login or cookies.

Designed for B2B sales, recruiting, and CRM teams who already have emails and need the matching public LinkedIn URL before outreach. This is the reverse of [LinkedIn Profile Email Scraper](https://apify.com/khadinakbar/linkedin-profile-email-scraper), which starts from a profile URL and looks for an email.

### What you get

| Output | What it answers |
|---|---|
| `email` + `matchStatus` | **Which address** was processed and whether a public profile was found |
| `profileUrl` + `publicIdentifier` | **Where** the person is on LinkedIn |
| `fullName`, `headline`, `currentCompany`, `location` | **Who they are** at work from public search and optional enrichment |
| `confidence`, `matchStrategy`, `provider` | **Why this match** was accepted, and which public-data provider supplied it |
| `clearReason` on CLEAR rows | **Why there is no billable match** — no public hit, role mailbox, or ambiguous result |
| `OUTPUT` / `RUN_SUMMARY` outcomes | **Provenance** — complete, empty, invalid input, or upstream outage |

### Who it is for (and why it matters)

- **Sales development reps** — attach a LinkedIn URL to inbound or list-bought work emails before a first touch.
- **Recruiters** — turn a candidate email list into public profiles so you can review headline, company, and location without a LinkedIn seat.
- **RevOps / CRM owners** — backfill contact records with a canonical `/in/` URL and skip role inboxes like `info@` without paying for them.
- **AI agents** — one tool call with `emails` returns structured found or CLEAR rows, so the agent can enrich, skip, or route without guessing.

### When to use this Actor

- You have work emails (`first.last@company.com`) and need public LinkedIn profile URLs.
- You want unmatched addresses recorded as CLEAR so the dataset stays honest.
- You need optional public-profile enrichment (company URL, followers, about) after a match.
- When you already have LinkedIn `/in/` URLs, start with [LinkedIn Profile Details Scraper](https://apify.com/khadinakbar/linkedin-profile-details-scraper) for the public about and experience view.
- When the starting point is a title, company, or location instead of an email, use [LinkedIn Profile Search Scraper](https://apify.com/khadinakbar/linkedin-profile-search-scraper).

### Best fit for this Actor

- Strongest starting condition: a work email whose local-part is a person's name and whose domain is the employer.
- Useful output: one row per email, billed only when `matchStatus` is `found`.
- When you need emails validated first, pass the list through [Email Address Validator](https://apify.com/khadinakbar/email-address-validator), then feed the surviving addresses here.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `emails` | array (required) | 1 example email | Up to 100 email addresses per run |
| `maxItems` | integer | 50 | Cap on **found** profiles saved and billed (CLEAR rows stay outside this cap) |
| `minConfidence` | integer | 70 | Minimum 0–100 score required to accept a match |
| `enrichProfiles` | boolean | false | Add company URL, location, followers, about ($0.02/row extra) |
| `providerOrder` | enum | `scrapecreators-first` | Public-data provider priority; fallback fires automatically |
| `maxConcurrency` | integer | 2 | Emails processed in parallel (1–5) |

#### Quick start input

```json
{
    "emails": ["satya.nadella@microsoft.com"],
    "maxItems": 1,
    "enrichProfiles": false
}
```

That input selects a single well-known work email so the run stays inside the five-minute quality window and still returns a real found row.

#### Example input — bulk work emails, enrichment on

```json
{
    "emails": [
        "satya.nadella@microsoft.com",
        "sundarpichai@google.com"
    ],
    "maxItems": 50,
    "minConfidence": 70,
    "enrichProfiles": true
}
```

Duplicate emails are deduplicated automatically. Role mailboxes such as `info@company.com` are written as CLEAR and never billed.

### What data you receive

One dataset item is one email lookup. Found rows carry the LinkedIn identity; CLEAR rows document that the lookup finished with no billable match.

```json
{
    "email": "satya.nadella@microsoft.com",
    "matchStatus": "found",
    "confidence": 88,
    "profileUrl": "https://www.linkedin.com/in/satyanadella",
    "publicIdentifier": "satyanadella",
    "fullName": "Satya Nadella",
    "headline": "Chairman and CEO at Microsoft",
    "currentCompany": "Microsoft",
    "matchStrategy": "name-company-site",
    "enriched": false,
    "provider": "scrapecreators",
    "scrapedAt": "2026-08-17T00:00:00.000Z"
}
```

CLEAR example:

```json
{
    "email": "info@microsoft.com",
    "matchStatus": "clear",
    "clearReason": "role_mailbox",
    "enriched": false,
    "scrapedAt": "2026-08-17T00:00:00.000Z"
}
```

Every terminal run also writes `OUTPUT` and `RUN_SUMMARY` with a named `outcome`, per-email results, provider diagnostics, and billing counters.

### Workflow story: from a CRM email column to outreach-ready LinkedIn URLs

A RevOps lead exports 40 work emails from a webinar registration list. She pastes them into this Actor with `enrichProfiles: true` and `maxItems` at 40. The run derives a name and company from each `first.last@company.com` address, searches public Google results restricted to LinkedIn profiles, and keeps only matches that clear the confidence bar. Twenty-eight rows come back `found` with profile URLs and current company; nine are CLEAR (`no_public_match` or `role_mailbox`); three stay unmatched because the local-part is a nickname with no public footprint. She then filters `matchStatus=found`, hands the `profileUrl` values to her sequencer, and skips paying for the CLEAR rows. Event cost is 28 × $0.025 plus enrichment on the rows that actually received public profile fields.

### Use through the API

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~email-to-linkedin-profile-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "emails": ["satya.nadella@microsoft.com"],
    "maxItems": 1,
    "enrichProfiles": false
  }'
```

Results land in the run's default dataset: `https://api.apify.com/v2/datasets/{datasetId}/items?clean=true`. Paginate large batches with `offset`/`limit`. The same Actor is exposed through Apify MCP as `apify--email-to-linkedin-profile-scraper`.

### Use with AI agents through Apify MCP

> Given these work email addresses, find each person's public LinkedIn profile URL, name, headline, and company. Return CLEAR for addresses with no public match. Keep only dataset `profileUrl` values. Cap the run at 25 found profiles.

Inspect the terminal `outcome`, read the dataset, keep `profileUrl` as the source identifier, and treat `clearReason` as a completed empty lookup for that address. Connect through [Apify MCP](https://mcp.apify.com).

```json
{
    "emails": ["satya.nadella@microsoft.com"],
    "maxItems": 25,
    "minConfidence": 70,
    "enrichProfiles": true,
    "providerOrder": "scrapecreators-first",
    "maxConcurrency": 2
}
```

Then read results with `get-actor-output`, keep `matchStatus=found` rows for outreach, and pass remaining emails to a validator or a different data source.

### Pricing

This Actor uses Pay per event plus Apify platform usage. Open the live Pricing tab for current event details, and use Apify's run cost controls to keep the workflow aligned with your budget.

| Event | Price | Charged when |
|---|---|---|
| Actor start | $0.00005 | Once per run (scaled by memory) |
| `profile-found` | $0.025 | One found LinkedIn profile saved |
| `profile-enriched` | $0.02 | Additional, only when enrichment succeeded |

CLEAR rows, invalid input, and unmatched emails are not billed as `profile-found`.

| Run | Found rows | Enrichment | Event cost (approx.) |
|---|---|---|---|
| 1 work email, match | 1 | off | ~$0.025 |
| 1 work email, match | 1 | on | ~$0.045 |
| 40 emails, 28 found | 28 | off | ~$0.70 |
| 40 emails, 28 found | 28 | on | ~$1.26 |

Your run log prints the exact cost cap before any charge fires. Platform usage is billed on top at Apify's rates — the live [Pricing tab](https://apify.com/khadinakbar/email-to-linkedin-profile-scraper/pricing) is the current source of truth.

### Best results

- Prefer `first.last@company.com` work emails; they produce name + company search queries.
- Run [Email Address Validator](https://apify.com/khadinakbar/email-address-validator) first when the list is messy, then look up the surviving addresses here.
- Keep `minConfidence` at 70 unless you have a reason to accept weaker name-only matches.
- Turn on `enrichProfiles` when you need location, followers, or a company page URL for routing.
- After you have profile URLs, pass them to [LinkedIn Profile Details Scraper](https://apify.com/khadinakbar/linkedin-profile-details-scraper) for the public about / experience view, or to [LinkedIn Profile Email Scraper](https://apify.com/khadinakbar/linkedin-profile-email-scraper) only when you started from a profile and need the reverse direction.

### Builder's note

I built this after probing ScrapeCreators and SociaVault live: neither vendor exposes an email-to-LinkedIn endpoint, and quoted `"email" site:linkedin.com/in` searches are usually empty because people rarely publish their inbox on a public profile. The working public path is Google Search over LinkedIn `/in/` results, using the name and company encoded in a work email, then scoring the hits so `satya.nadella@microsoft.com` keeps the Microsoft CEO and drops the identically named support specialist. That is why this Actor bills found profiles, writes honest CLEAR rows, and keeps ambiguous results out of the found set.

### Responsible use

Use this Actor on emails you are authorized to process for legitimate sales, recruiting, research, or verification. It reads **public web search results and public LinkedIn profile pages only**. It does not log into LinkedIn, does not use your cookies, and is not a private people-graph or data-broker dump. Follow GDPR, CCPA, CAN-SPAM, LinkedIn's terms, and any local law that applies to your outreach. Honor opt-out and do-not-contact requests.

This tool is provided for lawful public-data collection. You are responsible for how you use the output.

# Actor input Schema

## `emails` (type: `array`):

Email addresses to resolve to public LinkedIn profiles. Accepts work or personal emails such as satya.nadella@microsoft.com. Up to 100 addresses per run. Role mailboxes like info@ or support@ are recorded as CLEAR and are not billed. NOT LinkedIn profile URLs — use a profile scraper when you already have the /in/ URL.

## `maxItems` (type: `integer`):

Maximum number of matched LinkedIn profiles to save and bill this run. Default 50. CLEAR / not-found rows do not count toward this cap and are never billed. Prefill is 1 so Apify quality tests finish quickly; raise it for production batches.

## `minConfidence` (type: `integer`):

Minimum 0-100 confidence required to accept a LinkedIn profile as a match. Default 70. Lower values return more matches with a higher false-positive risk; higher values keep only name-and-company locks. This is not a LinkedIn login threshold.

## `enrichProfiles` (type: `boolean`):

When enabled, each found LinkedIn profile is fetched to add current company, company URL, location, follower count, and an about preview. Enrichment costs an additional $0.02 per successfully enriched profile on top of the $0.025 found-profile charge. Leave disabled when you only need the profile URL and SERP headline.

## `providerOrder` (type: `string`):

Which public-data provider to try first for Google Search and optional profile enrichment. Both providers return the same row shape; the fallback is used automatically when the primary fails or returns no results. Keep the default unless you have a reason to prefer SociaVault.

## `maxConcurrency` (type: `integer`):

How many email lookups to run in parallel. Default 2 balances speed against provider rate limits. Raise to 5 for large batches; lower to 1 if you see provider rate-limit errors in the run log.

## Actor input object example

```json
{
  "emails": [
    "satya.nadella@microsoft.com"
  ],
  "maxItems": 1,
  "minConfidence": 70,
  "enrichProfiles": false,
  "providerOrder": "scrapecreators-first",
  "maxConcurrency": 2
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset items containing email, matchStatus, LinkedIn profile URL, name, headline, company, location, and optional enrichment.

## `summary` (type: `string`):

Run summary including outcome, profilesFound, clearRows, provider diagnostics, and billing counters.

## `runSummary` (type: `string`):

Machine-readable RUN\_SUMMARY record mirroring OUTPUT for integrations that read RUN\_SUMMARY directly.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "emails": [
        "satya.nadella@microsoft.com"
    ],
    "maxItems": 1,
    "minConfidence": 70,
    "enrichProfiles": false,
    "maxConcurrency": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/email-to-linkedin-profile-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "emails": ["satya.nadella@microsoft.com"],
    "maxItems": 1,
    "minConfidence": 70,
    "enrichProfiles": False,
    "maxConcurrency": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/email-to-linkedin-profile-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "emails": [
    "satya.nadella@microsoft.com"
  ],
  "maxItems": 1,
  "minConfidence": 70,
  "enrichProfiles": false,
  "maxConcurrency": 2
}' |
apify call khadinakbar/email-to-linkedin-profile-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,khadinakbar/email-to-linkedin-profile-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/QNyRsYZSPWVlNZke2/builds/GhPS4D5jrtsKRBzxB/openapi.json
