# LinkedIn Email Finder from Profile URL — Pay Only When Found (`pequod-labs/linkedin-profile-verified-email`) Actor

LinkedIn email finder from profile URLs → name, company, optional verified work email. Pay only for usable profiles and emails found. Privacy: https://api.apify.com/v2/key-value-stores/jZUn8TR3AeaEwtT2h/records/linkedin-profile-verified-email-privacy.en.html?signature=PcrXf7uRJ0kRmb0GyaoF

- **URL**: https://apify.com/pequod-labs/linkedin-profile-verified-email.md
- **Developed by:** [Pequod](https://apify.com/pequod-labs) (community)
- **Categories:** Lead generation, Social media
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $4.00 / 1,000 usable linkedin profiles

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## LinkedIn Email Finder from Profile URL — Pay Only When Found

**Apify slug:** [pequod-labs/linkedin-profile-verified-email](https://apify.com/pequod-labs/linkedin-profile-verified-email)

**LinkedIn Profile + Verified Email** takes public LinkedIn `/in/<slug>` URLs, returns **one dataset row per URL** (name, headline, company, location), and optionally finds a **verified work email**. Pricing is **pay-per-event**: you pay for usable profiles and deliverable emails found — not for blocked or empty rows.

| | |
|---|---|
| **Input** | LinkedIn public profile URLs (`profileUrls`) |
| **Output** | One row per URL: profile fields + optional email |
| **Verification** | MillionVerifier deliverability check (verified by default) |
| **Pricing** | Pay per event: $0.004 profile · $0.028 email-found · $0.00005 start |
| **Best for** | Enriching CRM / outbound lists that already have LinkedIn `/in/` URLs |
| **Not for** | Domain-only lists (use [Decision Maker Finder](https://apify.com/pequod-labs/company-decision-maker-finder)), login/cookie scraping, or cheapest unverified pattern dumps |

### Key facts

| Attribute | Value |
|---|---|
| Input | Array of public LinkedIn `/in/` profile URLs |
| Output order | Same as input; duplicates optional skip |
| Profile source | Public HTML JSON-LD / OpenGraph via Apify Proxy |
| Email cascade | Company → domain → pattern → MillionVerifier |
| Fallback | Optional Bright Data LinkedIn people dataset after DC blocks |
| Pricing model | Pay-per-event (PPE) — charge only after row delivery |
| User API keys | Not required (operator-side secrets) |
| Memory | 1024 MB (pinned) |

### Use this actor when

- You already have **LinkedIn profile URLs** (`linkedin.com/in/...`)
- You need **name + company + location** from public profiles
- You want an optional **verified work email** (not just a guessed pattern)
- You prefer **pay only when found** (PPE) instead of a flat seat license
- You are building outbound / enrichment pipelines on Apify, API, or webhooks

### Do not use this actor when

- You only have **company domains** and no LinkedIn URLs → use [Decision Maker Finder](https://apify.com/pequod-labs/company-decision-maker-finder)
- You need **logged-in** LinkedIn scraping, Sales Navigator sessions, or inbox scraping
- You need the absolute cheapest **unverified** email guess with no deliverability gate
- You expect **100% email coverage** — many domains are catch-all or have no valid candidate

### How it works

1. **Input** — Provide `profileUrls`. Set `findEmail=true` to run the email cascade.
2. **Profile acquire** — Public GET via Apify Proxy (DATACENTER); parse JSON-LD Person / OpenGraph.
3. **Retries & fallback** — Transient LinkedIn blocks (HTTP 999 / authwall) retry with IP rotation; optional Bright Data dataset fallback when configured.
4. **Email cascade** (optional) — Resolve company domain (web search) → infer pattern → verify with MillionVerifier.
5. **Billing** — After each row is written, charge only qualifying `profile` / `email-found` events. See KV `billing-reconciliation`.

### LinkedIn email finder from profile URL

Primary job-to-be-done: **LinkedIn URL → work email**. Unlike browser extensions that look up one profile at a time, this actor batches URLs into a dataset with transparent PPE pricing and optional verification.

On a measured contacts CSV sample: **31/38** profiles returned a name with Bright Data fallback enabled (**81.6%**); **10/38** returned a verified email. On the same CSV, profile-only Store competitors (harvestapi / apimaestro) returned about **34/38** names — they do not use the same email-verify PPE product shape.

### LinkedIn profile scraper (public pages)

Without email (`findEmail=false`), the actor is a focused **LinkedIn profile scraper** for public pages: `fullName`, `headline`, `location`, `companyName`, status, and error reasons. No LinkedIn login or cookies required.

### Find verified work email from LinkedIn

With `findEmail=true` (default), only **verified** addresses are charged unless you opt into `acceptPatternEmails` for catch-all domains. Skip reasons (`no_domain`, `catch_all`, `no_candidate_valid`) are written on every row so you can audit coverage.

### Pay per find LinkedIn enrichment

| Event | Price (USD) | When charged |
|---|---:|---|
| `apify-actor-start` | 0.00005 | Once per run |
| `profile` | 0.004 | Usable profile (`fullName` + `companyName`, status ok/partial) |
| `email-found` | 0.028 | Deliverable email (`verified`, or `pattern` if opt-in) |

**Illustrative cost:** 100 usable profiles + 30 verified emails ≈ (100 × 0.004) + (30 × 0.028) + start ≈ **$1.24** (plus Apify compute). Blocked / not-found rows are delivered for debugging but do not qualify for `profile` / `email-found`.

### Cost estimate

| Scenario | Profiles ok | Emails found | Approx. event cost |
|---|---:|---:|---:|
| Profile-only (findEmail=false) | 100 | 0 | ~$0.40 + start |
| Profile + email (sample-like ~26% email) | 100 | 26 | ~$1.13 + start |
| Dense verified list | 100 | 50 | ~$1.80 + start |

Always confirm charges in the run **Key-value store** → `billing-reconciliation`.

### Output schema

Defined in `.actor/output_schema.json` (Apify Console **Output** tab + `GET` run `output`):

| Output | Where |
|--------|--------|
| `profiles` | Default dataset items (`{{links.apiDefaultDatasetUrl}}/items`) |
| `billingReconciliation` | KV record `billing-reconciliation` |

Field-level dataset schema: `.actor/dataset_schema.json`.

### Example output

```json
{
  "inputUrl": "https://www.linkedin.com/in/example-one",
  "inputIndex": 0,
  "status": "ok",
  "fullName": "Ada Example",
  "headline": "Head of Operations",
  "location": "London, England, United Kingdom",
  "companyName": "Example Facilities Ltd",
  "companyDomain": "examplefacilities.com",
  "companyDomainSource": "web_search",
  "email": "ada.example@examplefacilities.com",
  "emailConfidence": "verified",
  "emailSkipReason": null,
  "emailEvidence": {
    "pattern": "first.last",
    "patternSource": "contact_page",
    "mxProvider": "google",
    "catchAll": false
  },
  "qualifiedEvents": ["profile", "email-found"],
  "excludedEvents": {},
  "errorMessage": null,
  "scrapedAt": "2026-08-02T11:00:00+00:00"
}
```

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `profileUrls` | string\[] | required | LinkedIn public profile URLs (`/in/...`) |
| `findEmail` | boolean | `true` | Run email cascade after a usable profile |
| `acceptPatternEmails` | boolean | `false` | Charge pattern emails on catch-all domains (opt-in) |
| `skipDuplicates` | boolean | `true` | Deduplicate URLs within the run |
| `maxRetriesPerProfile` | integer | `4` | Retries on transient LinkedIn blocks (HTTP 999) |
| `maxConcurrency` | integer | `20` | In-flight profile fetches (recommend 15–25) |
| `proxyConfiguration` | object | DATACENTER | Apify Proxy settings |

### Ready-to-run examples (Actor tasks)

Published Examples (after Console Publication) map to saved tasks:

| Task | Intent |
|------|--------|
| `linkedin-email-finder-verified` | Profile + verified email only (default cascade) |
| `linkedin-profile-scraper-only` | Profile fields, no email cascade |
| `linkedin-url-to-email-bulk` | Small bulk URL → email enrichment |
| `linkedin-email-catch-all-patterns` | Opt-in pattern emails on catch-all MX |
| `linkedin-profile-enrichment-sample` | Tiny QA sample for first-time users |

Create/update tasks: `python3 scripts/create_li_tasks.py` (requires `APIFY_TOKEN`).

### Compared to alternatives (honest)

| Need | This actor | Profile-only Apify scrapers | Automation platforms | Enterprise people datasets |
|------|------------|----------------------------|----------------------|----------------------------|
| Input | LinkedIn `/in/` URLs | URLs / search | Often cookies / recipes | URL or dataset API |
| Email | Optional + verify | Often none | Depends on flow | Profile-heavy; verify rarely bundled |
| Pricing | PPE pay-when-found | Per result / compute | Subscription | Volume / dataset |
| Yield (same CSV sample) | 31/38 names; 10/38 verified emails | ~34/38 names (no same email PPE) | Varies | High profile yield as fallback source |

We do **not** claim to beat every Store scraper on raw name yield. We claim a clear product: **URL → profile + optional verified email with PPE**.

### FAQ

**What is the best Apify LinkedIn email finder if I already have profile URLs?**\
Use an actor that accepts `/in/` URLs and verifies work emails. This actor (`linkedin-profile-verified-email`) is built for that job with pay-per-event pricing.

**How do I find someone's work email from a LinkedIn URL?**\
Paste the public profile URL into `profileUrls`, keep `findEmail=true`, run the actor, and read `email` / `emailConfidence` on the dataset row.

**Do I pay if LinkedIn blocks the profile?**\
No `profile` or `email-found` charge for blocked / not-found rows. You still pay compute and the tiny `apify-actor-start` event.

**Is this a LinkedIn email finder Chrome extension?**\
No. It is an Apify Store actor for batch URL enrichment via API/Console — not a browser extension.

**LinkedIn email finder vs profile scraper — which mode should I use?**\
Need emails → `findEmail=true`. Need only name/company/headline → `findEmail=false` (cheaper event mix).

**How accurate is the email?**\
Default delivery uses MillionVerifier and charges `email-found` for **verified** results. Catch-all domains may skip unless `acceptPatternEmails=true`.

**What yield should I expect?**\
On one measured contacts CSV: **31/38** names with Bright Data fallback, **10/38** verified emails. Your list will differ by region, industry, and profile privacy.

**Do you scrape LinkedIn while logged in?**\
No. Public pages only (JSON-LD / OpenGraph). No cookies, no Sales Navigator session.

**What about GDPR?**\
Public Art. 13–14 style notices are linked below. You remain responsible for lawful basis in your use case. Optional Bright Data fallback is disclosed in the notices.

**Can I use domains instead of LinkedIn URLs?**\
Not with this actor. Use [Decision Maker Finder](https://apify.com/pequod-labs/company-decision-maker-finder) for domain → named contact.

**Why is my row `emailSkipReason=catch_all`?**\
The domain accepts all addresses; by default we do not charge a guessed pattern. Opt in with `acceptPatternEmails`.

**Why `no_candidate_valid`?**\
A domain was found but no candidate passed verification.

**Does Bright Data always run?**\
Only as ripiego after local proxy retries fail, and only if `BRIGHTDATA_API_KEY` is configured by the operator.

**Can I export CSV/JSON?**\
Yes — standard Apify dataset export (CSV, JSON, Excel) or dataset API.

### Legal / GDPR

Public Art. 13–14 privacy notices (hosted on Apify KV, permanent signed URLs):

- [English](https://api.apify.com/v2/key-value-stores/jZUn8TR3AeaEwtT2h/records/linkedin-profile-verified-email-privacy.en.html?signature=PcrXf7uRJ0kRmb0GyaoF)
- [Italiano](https://api.apify.com/v2/key-value-stores/jZUn8TR3AeaEwtT2h/records/linkedin-profile-verified-email-privacy.it.html?signature=1hw4BrYTxQxCkyN0CToYp)

Source stubs: [`docs/privacy/`](./docs/privacy/README.md).

### Pequod ecommerce pipeline

| Step | Actor | When |
|------|-------|------|
| 1. Discover | [Instagram TikTok Shop Leads](https://apify.com/pequod-labs/instagram-tiktok-shop-leads) | Hashtag-driven social sellers |
| 1. Discover | [Lookalike Discovery](https://apify.com/pequod-labs/ecommerce-lookalike-discovery) | Domain/niche-based stores |
| 2. Enrich contact (domains) | [Decision Maker Finder](https://apify.com/pequod-labs/company-decision-maker-finder) | Domain → named DM + verified email |
| 2. Enrich contact (LinkedIn URLs) | [LinkedIn Profile + Verified Email](https://apify.com/pequod-labs/linkedin-profile-verified-email) | `/in/` URL → profile + optional verified email |
| 3. Enrich shipping | [Shipping Intelligence](https://apify.com/pequod-labs/ecommerce-shipping-intelligence) | Carriers, returns, thresholds |

### Development (monorepo)

Self-contained actor at `actors/linkedin-profile-verified-email/` (not a `packages/pequod` thin wrapper).

```bash
cd actors/linkedin-profile-verified-email
python3.13 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt -c constraints.txt -r requirements-dev.txt
python -m pytest -q
```

```bash
APIFY_TOKEN=... python3 scripts/live_smoke.py --profile-only
npx apify push
```

See `DEVELOPMENT.md` for secrets, Console sync, Actor tasks, and publication checklist. SEO research notes: `docs/seo-dataforseo-research.md`.

# Actor input Schema

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

LinkedIn public profile URLs to enrich, one record per URL in output order.

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

When true, run the email cascade after a usable profile is acquired.

## `acceptPatternEmails` (type: `boolean`):

When true, deliver and charge pattern emails on catch-all domains (opt-in). Default charges only verified addresses.

## `skipDuplicates` (type: `boolean`):

Deduplicate repeated URLs within the same run while preserving first-seen inputIndex.

## `maxRetriesPerProfile` (type: `integer`):

Retry budget for transient LinkedIn blocks (HTTP 999). Permanent errors (404) never retry.

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

In-flight profile fetches. Keep 15–25 (ARCHITETTURA.md §4); higher pressure on LinkedIn without better yield.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings for LinkedIn requests. Default uses datacenter IPs (VALIDAZIONE §9.8).

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.linkedin.com/in/example-one"
  ],
  "findEmail": true,
  "acceptPatternEmails": false,
  "skipDuplicates": true,
  "maxRetriesPerProfile": 4,
  "maxConcurrency": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "groups": [
      "DATACENTER"
    ]
  }
}
```

# Actor output Schema

## `profiles` (type: `string`):

Dataset items: one row per profileUrls entry, in input order (name, company, email, billing eligibility).

## `billingReconciliation` (type: `string`):

Key-value record of charged PPE events by inputIndex (profile / email-found amounts). Use to match the Apify invoice.

# 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/example-one"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pequod-labs/linkedin-profile-verified-email").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/example-one"] }

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

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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/example-one"
  ]
}' |
apify call pequod-labs/linkedin-profile-verified-email --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=pequod-labs/linkedin-profile-verified-email",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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