# LinkedIn Profile Email Finder (`blueskyscraper/linkedin-profile-email-finder`) Actor

Find the work e-mail of LinkedIn profiles, no login or cookies: the person's company website, the address layout it uses, a mail-server check and a confidence level, plus the full profile with title, company and experience. E-mail price only for an e-mail at your minimum confidence.

- **URL**: https://apify.com/blueskyscraper/linkedin-profile-email-finder.md
- **Developed by:** [BlueskyScraper](https://apify.com/blueskyscraper) (community)
- **Categories:** Lead generation, Automation, Agents
- **Stats:** 4 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $6.80 / 1,000 profile with e-mails

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**LinkedIn Profile Email Finder** finds the **work e-mail** of people from their LinkedIn profile URLs, **without a login, cookies or an API key**. For each person it finds the company's own website, learns **how that company writes its addresses**, builds the address, checks that the domain **accepts mail**, and tells you **how sure it is** — next to the profile itself (name, headline, company, location, followers). **$8 per 1,000 e-mails found** at your minimum confidence (default `medium` — the company's own site confirms the address layout); profiles without an e-mail cost $3.2 per 1,000.

### What is LinkedIn Profile Email Finder?

A **LinkedIn email finder** for sales prospecting, recruiting outreach and lead enrichment. Paste profile links — `https://www.linkedin.com/in/kippbodnar` or just `kippbodnar` — and get a sheet with each person's work e-mail, confidence and evidence. It works as a **LinkedIn to email API** from Python, JavaScript, Make, Zapier or n8n. No LinkedIn account is used, so yours cannot be restricted, and no third-party e-mail database is resold: every address is worked out from the company's own public website at the time of the run.

### How the e-mail is found

1. **Company** — the current company from the profile (or your **Company override**).
2. **Domain** — the company's website, accepted only with evidence: linked from its LinkedIn page, the domain spells the company name, the site carries the company name, or it is a known parent company. A domain that cannot be backed is **not used** — no address is built on a guess.
3. **Layout** — a few pages of the company site are read; addresses published there show the layout (`first.last`, `flast`, `first`, `firstl`…).
4. **Mail check** — DNS **MX lookup**: only an address on a domain that accepts mail can be delivered as an e-mail. No test e-mails are sent and no mailbox (SMTP) check is made, so the Actor never calls an address "deliverable".
5. **Confidence** — `confirmed` (the address itself is on the company's site, `emailStatus: found-on-website`), `high` / `medium` (the layout is seen on the site, `pattern-confirmed`), `low` (the most common layout, nothing confirms it, `unverified-guess`). Only addresses at or above **Minimum e-mail confidence** (default `medium`) go into `email` and are billed as e-mails; a weaker guess is kept in `emailGuess` and the row is a plain profile.

Measured on 15 profiles of people at software companies and small firms (3 October 2026): **13 rows came with an address** — 2 confirmed on the company site, 11 built in the most common layout on a mail-accepting domain; the other 2 profiles list no current company. With the default minimum confidence (`medium`, since 5 October 2026) only the 2 confirmed addresses are delivered and billed as e-mails; the 11 common-layout guesses come in `emailGuess` at the plain profile price. Set the minimum to `low` to get them in `email` (and pay the e-mail price).

### What data does it return?

| Field | Example |
|---|---|
| `email` | samantha@samsalesconsulting.com |
| `confidence` | confirmed |
| `emailStatus` | found-on-website (`pattern-confirmed`, `unverified-guess`; `undeliverable` / `risky` / `unknown` when the domain fails the DNS check) |
| `emailGuess` | the best address when it is not put into `email` — free |
| `emailDomainStatus` | accepts-mail |
| `domain` / `domainEvidence` | samsalesconsulting.com / the company's LinkedIn page links this website |
| `emailPattern` / `emailPatternSource` | first / site |
| `foundOnSite` | true |
| `alternatives` | samantha.mckenna@…, smckenna@… |
| `emailProvider`, `emailMxHost`, `emailIsRole`, `emailIsFree`, `emailIsDisposable` | mail-server facts |
| `summary` | samantha@samsalesconsulting.com is published on samsalesconsulting.com itself. |
| profile | `fullName`, `headline`, `title`, `company`, `location`, `followers`, `connections`, `about`, `education`, `linkedinUrl`… |

#### How often each profile field is filled

LinkedIn shows logged-out visitors a shorter profile than members see. Measured on 55 mixed profiles (3 October 2026):

| Filled in | Profile fields |
|---|---|
| **Every profile** | `fullName`, `headline` (as in the page title — for 7 in 10 people that is their current company), `location`, `country`, `followers`, `connections`, `imageUrl`, `linkedinUrl` |
| **Most profiles** | `company` and `companyLinkedinUrl` (9 in 10), `about` (3 in 4), `recommendations` (7 in 10), `education` (6 in 10), `website` (5 in 10) |
| **Some profiles** | `certifications`, `honorsAndAwards`, `languages`, `volunteering`, `publications` (1 in 4 to 1 in 3) |
| **Few profiles** | job `title` and full `experience` with titles and dates (about 1 in 5 — LinkedIn masks past employers for logged-out visitors), `skills` (about 1 in 8) |

Added 5 October 2026 (checked on 7 public profiles): every role in the Experience section, including each role inside a company group (one long career went from 11 to 24 roles), with `companyLogo` and `location`; every school in the Education section with `degree` and `fieldOfStudy` (schools without dates used to be missing); `city`, `region`, `countryCode`; `coverImageUrl`, `memberId`, `profileUrn`; `languageProficiencies`, `courses`, `projects`, `testScores`, `coursesTaught` when the profile shows those sections. The exact connection count, Featured, interests and open-to-work / hiring flags are not shown to logged-out visitors, so they are not returned.

Added 5 October 2026 (round 2): `similarProfiles` — the "Other similar profiles" side rail of the public profile (LinkedIn's "People also viewed" as logged-out visitors see it): name, headline as the card shows it (usually the current company), location, followers, profile URL and photo of each person, 9–20 per profile (10 of 11 checked profiles show it). `sameNameProfiles` — "Others named …", when LinkedIn shows that rail (1 of 11). Same page, no extra request or charge.

An empty field means LinkedIn did not show it, not that the run failed.

### 💰 How much does it cost to find e-mails from LinkedIn?

| Row | Price |
|---|---|
| **Profile with e-mail** — `email` is filled: confidence at or above your minimum (default `medium`) | $0.008 — $8 per 1,000 |
| **Profile** (no e-mail could be backed, or only a guess below your minimum confidence in `emailGuess`) | $0.0032 — $3.2 per 1,000 |

Each row is billed once, as one or the other. No start fee, proxies included. Hidden and non-existent profiles are **free error rows**. Apify's free plan ($5 of monthly credit) covers about **600 e-mails a month**. Paid Apify plans get tiered discounts automatically.

### How to find e-mails from LinkedIn profiles

1. Click **Try for free**.
2. Paste profile URLs or slugs into **👤 LinkedIn profiles**, or link a Google Sheet / CSV in **📄 URLs from a file or sheet**.
3. Optional: raise **Minimum e-mail confidence**, or set **Company override** (e.g. `hubspot.com`) when the whole list works at one company.
4. Click **Start**; open the **Work e-mails** view and export it.

### ⬇️ Input

```json
{
    "profileUrls": [
        "https://www.linkedin.com/in/kippbodnar",
        "https://www.linkedin.com/in/wadefoster",
        "https://www.linkedin.com/in/satyanadella"
    ],
    "findEmail": true,
    "minConfidence": "medium"
}
```

### ⬆️ Output

```json
{
    "type": "profile",
    "fullName": "Samantha McKenna",
    "title": "Chief Executive Officer",
    "company": "#samsales Consulting",
    "email": "samantha@samsalesconsulting.com",
    "confidence": "confirmed",
    "emailStatus": "found-on-website",
    "emailGuess": null,
    "emailDomainStatus": "accepts-mail",
    "domain": "samsalesconsulting.com",
    "domainSource": "linkedin",
    "emailPattern": "first",
    "foundOnSite": true,
    "alternatives": [
        { "email": "samantha.mckenna@samsalesconsulting.com", "pattern": "first.last" },
        { "email": "smckenna@samsalesconsulting.com", "pattern": "flast" }
    ],
    "summary": "samantha@samsalesconsulting.com is published on samsalesconsulting.com itself.",
    "linkedinUrl": "https://www.linkedin.com/in/samsalesli"
}
```

When no address can be backed, `email` is empty and `summary` says why — no current company, a company without its own mail domain, a domain that could not be confirmed, or a domain that takes no mail.

### What LinkedIn shows without a login

This Actor reads the **public pages LinkedIn serves to logged-out visitors and search engines** — no account, no cookies, nothing that could get an account banned. That decides what is possible:

- **Hidden profiles.** Some people hide their profile from logged-out visitors; LinkedIn then answers with a login wall or HTTP 999 for that profile from every address. On mixed lists about **1 in 4 or 5** profiles is refused on the first route. Those get **one more try through an unblocking route, paid only from your run's own margin** (never from a subsidy that would have to be priced in). Whatever still stays hidden comes back as a **free error row** saying so.
- **Recent posts only.** A logged-out visitor sees a company's **~10 newest posts** (median 9 on a 20-company check, 2 of 20 showed none) and a person's **~5–10 newest posts, quote-shares and reposts** **plus up to 10 articles**. A page with fewer posts than you asked for adds one free `notice` row saying how many LinkedIn showed. There is no paging back to older posts without a login — use the **Only posts not delivered before** switch on a daily schedule to build a full history from now on.
- **Shortened surnames.** A few profiles show the surname as an initial ("Diego C.") to logged-out visitors; the row says so.
- **No private data.** Phone numbers, connections lists and contact info behind the login are not read.

Pages that do not exist (HTTP 404) are free error rows too. A run in which LinkedIn refuses everything ends with error rows and no charge.

### Use cases

#### Sales prospecting

Turn a list of decision makers' LinkedIn URLs into an outreach list with work e-mails.

#### Recruiting outreach

Reach candidates at their work address with the evidence of how it was built.

#### CRM enrichment

Fill the e-mail column for contacts that only have a LinkedIn link.

### Integrations and API

Use **LinkedIn Profile Email Finder** like any Apify Actor:

- **API**: start a run and read the dataset over HTTP — see the **API** tab for ready-made calls.
- **Python**:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("blueskyscraper/linkedin-profile-email-finder").call(run_input={"profileUrls": ["https://www.linkedin.com/in/kippbodnar", "https://www.linkedin.com/in/wadefoster", "https://www.linkedin.com/in/satyanadella"]})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row)
```

- **JavaScript**:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('blueskyscraper/linkedin-profile-email-finder').call({"profileUrls": ["https://www.linkedin.com/in/kippbodnar", "https://www.linkedin.com/in/wadefoster", "https://www.linkedin.com/in/satyanadella"]});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

- **No-code**: Make, Zapier, n8n, Google Sheets, Airtable, Slack and webhooks through Apify integrations — send every finished run's rows wherever your team works.
- **AI agents (MCP)**: add the Actor to Claude, ChatGPT, Cursor or any MCP client through the Apify MCP server (`https://mcp.apify.com`) and ask for LinkedIn data in plain words.
- **Schedules**: run it every day or week from the **Schedules** page; combine with **Maximum results per run** to cap the bill.

### ❓ FAQ

#### Is it legal to scrape LinkedIn?

The Actor reads only pages that LinkedIn shows to anyone without an account. Scraping public data is generally lawful, but names, job titles and e-mails are **personal data** under laws such as the GDPR and CCPA: have a lawful reason to process them, keep them safe, and honour opt-outs. When in doubt, ask a lawyer.

#### Do I need a LinkedIn account, cookies or a proxy?

No. Nothing to log in to, no cookies to paste, no proxy to set up — your own LinkedIn account is never touched, so it cannot be restricted. Proxies are included in the price.

#### Can I use it with the Apify API?

Yes — every run can be started and read over the Apify API, from Python, JavaScript or any HTTP client. See **Integrations and API** above.

#### Can I use it through an MCP server?

Yes. Add it to the Apify MCP server (`https://mcp.apify.com`) and your AI assistant can call it directly.

#### Can I integrate it with other apps?

Yes: Make, Zapier, n8n, Google Sheets, Airtable, Slack and webhooks through Apify integrations.

#### Why did some pages come back as error rows?

Either the page does not exist (404), or LinkedIn hides it from logged-out visitors. Both are **free** — you pay only for rows with data. The `error` field says which.

#### Do I pay for errors, filtered-out posts or the start of a run?

No. There is no start fee; error rows and posts removed by your filters are never billed. **Maximum results per run** and Apify's **Max cost per run** are hard ceilings — when the cost limit is reached, the run stops by itself with everything written already paid for.

#### Are the e-mails verified?

The domain is checked for a mail server (MX record) and the layout comes from the company's own site when it publishes addresses. Mailboxes are not probed (no test e-mail, no SMTP handshake), so `emailStatus` and `confidence` tell you how much evidence there is — and by default only addresses the company's own site backs up (`pattern-confirmed` or `found-on-website`) are billed as e-mails. Run the list through an e-mail verifier before a large campaign.

#### What if the profile has no current company?

The row stays a plain profile with a `summary` explaining why. Fill **Company override** when you know the company.

### Your feedback

Something missing or wrong? Open an issue on the **Issues** tab — we read every one.

### You might also like

| Actor | What it does |
|---|---|
| [LinkedIn Scraper](https://apify.com/blueskyscraper/linkedin-scraper) | Profiles, work e-mails, company pages and latest posts in one Actor |
| [LinkedIn Profile Details Scraper](https://apify.com/blueskyscraper/linkedin-profile-details-scraper) | Full public profiles from a list of profile URLs |
| [LinkedIn Company Details Scraper](https://apify.com/blueskyscraper/linkedin-company-details-scraper) | Company pages: website, industry, size, followers, address |
| [LinkedIn Company Posts Scraper](https://apify.com/blueskyscraper/linkedin-company-posts-scraper) | Latest posts of company pages with likes and comments |
| [LinkedIn Profile Posts Scraper](https://apify.com/blueskyscraper/linkedin-profile-posts-scraper) | Latest posts and articles of people |

# Actor input Schema

## `profileUrls` (type: `array`):

Profile URLs or slugs, one per line — <code>https://www.linkedin.com/in/satyanadella</code> or just <code>satyanadella</code>. Profiles that do not exist or that LinkedIn hides from logged-out visitors come back as free error rows.

## `startUrls` (type: `array`):

For long lists: upload a file or link a Google Sheet (or any text / CSV URL) that contains LinkedIn URLs. Each link is routed by its kind.

## `findEmail` (type: `boolean`):

Find each person's work e-mail — the company's website, the address layout it uses, a mail-server (MX) check and a confidence level. A row WITH an e-mail is billed as <i>Profile with e-mail</i>; a row without one stays a plain <i>Profile</i>.

## `minConfidence` (type: `string`):

An address below this level is not put into <code>email</code> (it goes to <code>emailGuess</code> and <code>alternatives</code>) and the row is billed as a plain profile. <b>confirmed</b> = published on the company's site; <b>high / medium</b> = the layout is seen on the site (pattern-confirmed); <b>low</b> = the most common layout, nothing confirms it (unverified-guess). No mailbox (SMTP) check is made.

## `companyOverride` (type: `string`):

Use this company name or domain for everyone instead of what the profiles say — e.g. <code>hubspot.com</code> when the whole list works at one company.

## `candidatesPerPerson` (type: `integer`):

The best address goes into <code>email</code>, the runners-up into <code>alternatives</code>.

## `maxPagesPerCompany` (type: `integer`):

Home page plus contact / team / about pages, read to learn how the company writes its addresses.

## `pageTimeoutSecs` (type: `integer`):

How long to wait for one company web page.

## `includePosts` (type: `boolean`):

The person's recent posts and articles that LinkedIn shows logged-out visitors, inside the same row. No extra charge.

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

A hard ceiling on the rows one run bills — profiles, companies or posts.

## `concurrency` (type: `integer`):

How many LinkedIn pages to read at the same time. Keep it low — LinkedIn dislikes bursts.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/kippbodnar",
    "https://www.linkedin.com/in/wadefoster",
    "https://www.linkedin.com/in/satyanadella"
  ],
  "findEmail": true,
  "minConfidence": "medium",
  "candidatesPerPerson": 3,
  "maxPagesPerCompany": 4,
  "pageTimeoutSecs": 15,
  "includePosts": false,
  "maxItems": 10000,
  "concurrency": 3
}
```

# Actor output Schema

## `rows` (type: `string`):

One row per profile, company or post; free error rows explain pages that could not be read.

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

Counts, routes and proxy use of the run.

# 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 = {
    "profileUrls": [
        "https://www.linkedin.com/in/kippbodnar",
        "https://www.linkedin.com/in/wadefoster",
        "https://www.linkedin.com/in/satyanadella"
    ],
    "minConfidence": "medium"
};

// Run the Actor and wait for it to finish
const run = await client.actor("blueskyscraper/linkedin-profile-email-finder").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 = {
    "profileUrls": [
        "https://www.linkedin.com/in/kippbodnar",
        "https://www.linkedin.com/in/wadefoster",
        "https://www.linkedin.com/in/satyanadella",
    ],
    "minConfidence": "medium",
}

# Run the Actor and wait for it to finish
run = client.actor("blueskyscraper/linkedin-profile-email-finder").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 '{
  "profileUrls": [
    "https://www.linkedin.com/in/kippbodnar",
    "https://www.linkedin.com/in/wadefoster",
    "https://www.linkedin.com/in/satyanadella"
  ],
  "minConfidence": "medium"
}' |
apify call blueskyscraper/linkedin-profile-email-finder --silent --output-dataset

```

## MCP server setup

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

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/EnGTepJdNsPBRqwJV/builds/VIffGhXr2GCG6avir/openapi.json
