# LinkedIn Decision Maker Finder – Sales Navigator, No Cookies (`leadsfactory/leadsfactory-lead-finder`) Actor

Find decision makers at up to 50 companies from a live LinkedIn Sales Navigator search. No LinkedIn account, no cookies. Give company domains and job titles; AI expands each title, scores every candidate 0-100 and returns the best matches with the reason. Profile data only, no emails.

- **URL**: https://apify.com/leadsfactory/leadsfactory-lead-finder.md
- **Developed by:** [Brahim Sliti](https://apify.com/leadsfactory) (community)
- **Categories:** Lead generation, Social media, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $120.00 / 1,000 contact delivereds

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/actors/running/actors-in-store.md#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 Decision Maker Finder – Sales Navigator, No Cookies

Give it a list of company domains and the job titles you sell to. It runs a live LinkedIn Sales Navigator search for each company, scores every candidate with AI, and returns the best-matching people, each with the reason they matched (3 per title by default, up to 25).

**Test run: $0.41.** One company, one job title, 3 scored contacts, 3–5 minutes.
**Per run:** up to 50 companies × 5 job titles. **Output:** LinkedIn profile and company fields, CSV / JSON / Excel. **No emails or phones.**

**No LinkedIn account to connect. No cookie to paste.** The search runs on LeadsFactory's own managed LinkedIn accounts.
**LinkedIn profile and company data only.** No email addresses, no phone numbers. See [Getting emails](#getting-emails).

One run, one dataset. Some no-cookie scrapers hand you a job ID and make you run a second actor to collect the rows. Here the contacts land in this run's dataset while it is still going.

### Who this is for

- Anyone who opened a Sales Navigator scraper, got asked for their `li_at` cookie, and closed the tab.
- SDRs and founders with a target account list who need the right person at each account, not 2,000 raw profiles.
- Agencies filling "Head of X at these 50 companies" lists for clients.
- RevOps and growth teams feeding Clay, n8n, Make, HubSpot, Salesforce or Google Sheets from the API.

Already have a Sales Navigator search URL and want every profile in it? Use [LinkedIn Sales Navigator Scraper (No Cookies)](https://apify.com/leadsfactory/leadsfactory-sales-navigator-scraper) instead.

### How the Sales Navigator search works

1. **You provide companies and titles.** Website domains (`stripe.com`) or LinkedIn company URLs, up to 50 per run. One to five job titles, for example `Head of Sales`.
2. **AI expands each title.** Real companies do not follow your title conventions: the person running sales at a German mid-market company is a `Leiter Vertrieb`, not a `Head of Sales`. `Head of Sales` also covers `VP Sales`, `Sales Director`, `Directeur Commercial` and similar, so you get a match at companies a literal keyword search misses. Turn on *Exact job titles only* to skip this step.
3. **Sales Navigator is searched live** for each company on LeadsFactory's managed accounts. Not a static database: you get what Sales Navigator shows at the moment you run, including recent job changes, rather than a snapshot rebuilt every few months.
4. **Every candidate is scored 0–100** against the title you asked for. You get the top matches per title per company, each with `ai_score` and a one-sentence `score_reason`.

Rows stream into the dataset while the run is still going, so you can start working on the first companies before the last ones finish.

**Real run:** `stripe.com` × `Head of Sales`, 3 contacts requested. 3 scored Heads of Sales returned in 3 minutes 30 seconds on a cold search, and in about 20 seconds when the same company had been searched before.

**Estimated delivery time:** 3–5 minutes for one company. Companies run in parallel. For 50 companies, or several titles, set `maxWaitMinutes` to 60 rather than the 30-minute default.

### What you pay, and when

Pay per event. No LeadsFactory subscription, no Sales Navigator seat. Apify platform usage (compute, proxies) is included in these prices; you are not billed separately for it.

| Event | Price | Charged when |
|---|---|---|
| Company searched (`company-searched`) | $0.05 | A company was matched to its LinkedIn page and searched. Charged once per company, whether or not a matching contact is found. Companies that cannot be matched, or whose match looks doubtful, are not charged. |
| Contact delivered (dataset item) | $0.12 | A scored contact row is written to your dataset. Contacts below the score threshold are never delivered and never charged. |

Profile scrapers charge about $0.01 a row because they hand you every row a search returns. Here you pay for the answer, not the haystack: each $0.12 row was searched for, scored against your title, and kept because it cleared the bar. Everything below the bar is discarded and never billed.

Worked examples:

| Run | Input | Contacts delivered | Cost |
|---|---|---|---|
| Test | 1 company × 1 title | 3 | $0.05 + $0.36 = **$0.41** |
| Account list | 10 companies × 1 title | 30 | $0.50 + $3.60 = **$4.10** |
| Full run | 50 companies × 1 title | 150 | $2.50 + $18.00 = **$20.50** |
| Two personas | 50 companies × 2 titles | 300 | $2.50 + $36.00 = **$38.50** |
| Maximum possible | 50 companies × 5 titles × 25 contacts | 6,250 | $2.50 + $750.00 = **$752.50** |

**Before your first large run, set a maximum cost per run in the Apify Console.** The actor stops cleanly at your budget and keeps everything collected so far. Worst case for any input is `companies × $0.05 + companies × titles × maxContactsPerJobTitle × $0.12`.

What you can hold us to:

- A company with no matching contact costs $0.05, not a full search fee.
- Input errors (no companies, more than 50 companies, no titles) fail before any charge.
- Companies that cannot be resolved to a LinkedIn page are listed in `OUTPUT` with the reason. They are not charged.
- When a domain is matched to a page whose name does not look like the domain, the log flags it ("Check this match") and `OUTPUT.companies_resolved` shows what each domain resolved to. Pass the LinkedIn company URL when you need an exact match.
- If `maxWaitMinutes` runs out, the run ends with everything collected so far and the log says so. Diff your input against `company_domain` in the dataset to re-run only the companies that had no result yet.

How this compares, honestly:

| Approach | 50 companies, 3 contacts each | What you get |
|---|---|---|
| **This actor** | **$20.50** | No Sales Navigator seat. One input: domains and titles. Every company is searched individually, so you get coverage per account. Each contact carries a 0–100 score and a one-line reason. |
| One filtered Sales Navigator search with all 50 companies in the *Current company* filter, exported by a no-cookie URL scraper ($0.50 per search + $0.01 per result) | About $3.50 for ~300 rows, plus your Sales Navigator seat | Cheapest per row. You build the filter, some accounts return nothing and others 40 rows, and you read the 300 profiles to pick the right person at each company. |

We are not the cheapest per row and do not claim to be. $20.50 is $0.41 per account for the named decision-maker and the reason they are the one. If you want raw volume from one search URL, the [Sales Navigator Scraper](https://apify.com/leadsfactory/leadsfactory-sales-navigator-scraper) is priced for that.

### Input

| Field | Type | Required | Default | What it does |
|---|---|---|---|---|
| `companyDomains` | string\[] | one of the two | – | Company websites, e.g. `stripe.com`. Each domain is resolved to its LinkedIn company page. |
| `companyLinkedinUrls` | string\[] | one of the two | – | LinkedIn company page URLs, e.g. `https://www.linkedin.com/company/stripe/`. Skips domain resolution; the most reliable input when you have it. |
| `jobTitles` | string\[] | yes | – | 1 to 5 titles. One entry per persona you want at each company. |
| `maxContactsPerJobTitle` | integer | no | `3` | Contacts returned per title per company (1–25). |
| `seniorityLevels` | string\[] | no | auto | Keep only these levels: Owner, Partner, C-suite, VP, Director, Head, Manager, Senior, Entry. If empty, the seniority implied by the title is used. |
| `countryCodes` | string\[] | no | worldwide | ISO-2 codes, e.g. `US`, `FR`, `DE`. Filters on the contact's location. |
| `exactJobTitlesOnly` | boolean | no | `false` | Match titles literally. No synonyms, no translations. |
| `maxWaitMinutes` | integer | no | `30` | Stop after this many minutes and keep what was found (5–120). |

Domains and LinkedIn URLs count together towards the 50-company limit.

#### Input example

```json
{
    "companyDomains": ["stripe.com", "shopify.com", "notion.so"],
    "jobTitles": ["Head of Sales", "VP Marketing"],
    "maxContactsPerJobTitle": 3,
    "seniorityLevels": ["Head", "VP", "Director"],
    "countryCodes": ["US", "GB"]
}
```

### What you get: LinkedIn profile and company fields

One dataset row per contact. Fields with no data are `null`. Example row (illustrative: fictional person and company):

```json
{
    "company_name": "Northwind Logistics",
    "company_linkedin_url": "https://www.linkedin.com/company/northwind-logistics",
    "company_domain": "northwind-logistics.example",
    "company_industry": "Transportation, Logistics, Supply Chain and Storage",
    "company_employee_count": 850,
    "company_location": "Rotterdam, South Holland",
    "company_country": "NL",
    "job_title_searched": "Head of Sales",
    "ai_score": 92,
    "score_reason": "Current Head of Sales for the Benelux region, direct match for the requested title",
    "first_name": "Anna",
    "last_name": "Example",
    "full_name": "Anna Example",
    "job_title": "Head of Sales - Benelux",
    "headline": "Head of Sales - Benelux at Northwind Logistics",
    "linkedin_url": "https://www.linkedin.com/in/anna-example",
    "location": "Rotterdam, Netherlands",
    "about": "Building and leading B2B sales teams in logistics ...",
    "current_company": "Northwind Logistics",
    "current_role_description": "Leading a team of six account executives selling to enterprise shippers ...",
    "months_in_role": 15,
    "months_at_company": 59,
    "open_to_inmail": true,
    "premium_profile": true
}
```

| Group | Fields |
|---|---|
| Company | `company_name`, `company_linkedin_url`, `company_domain`, `company_industry`, `company_employee_count`, `company_location`, `company_country` |
| Match | `job_title_searched`, `ai_score` (0–100), `score_reason` |
| Person | `first_name`, `last_name`, `full_name`, `job_title`, `headline`, `linkedin_url`, `location`, `about` |
| Current role | `current_company`, `current_role_description`, `months_in_role`, `months_at_company` |
| LinkedIn flags | `open_to_inmail`, `premium_profile` |

Download from the Dataset tab as CSV, JSON or Excel, or read it from the API. The run's `OUTPUT` record in the key-value store holds the summary: search status, contacts found, companies with no match (`companies_with_no_results`), and companies that could not be resolved (`companies_with_errors`, with the reason).

### Getting emails

This actor returns LinkedIn identity and firmographic data. It does not return email addresses or phone numbers.

Every row has `linkedin_url`. Pass it to your email-finding step: an enrichment actor on Apify, a Clay waterfall, or any enrichment API that accepts a LinkedIn profile URL. Because the contact is already the scored match for the role, you enrich 3 people per company instead of 300.

**Free Apify plan.** Runs started from a free Apify plan are limited to 1 company × 1 job title × 2 contacts
(enough to see real output). Any paid Apify plan unlocks the full limits: 50 companies, 5 titles, 25 contacts
per title. The run log says when a limit was applied.

### Limits, plainly

- Up to **50 companies** and **5 job titles** per run. For more, run the actor in a loop from the API, 50 companies at a time.
- Up to **25 contacts** per title per company.
- Runs take **minutes**, not seconds. See estimated delivery time above.
- **No email addresses, no phone numbers.**
- Domains are resolved to a LinkedIn company page automatically. Unresolvable domains are skipped and listed in `OUTPUT`. A doubtful domain-to-company match is flagged in the run log with the advice to pass the LinkedIn company URL instead. If you already know the page, pass `companyLinkedinUrls`; it skips resolution and is the most reliable input.
- Some companies have nobody matching a title. That is a real answer, not a bug. They appear in `companies_with_no_results`.
- Rows are unique within a run (company, contact, title). Runs are independent: the same input twice returns the same people twice, and bills twice. Dedupe on `linkedin_url` downstream.
- Sales Navigator data is what LinkedIn shows at run time. People who hide their profile from search are not returned.
- The managed accounts are the same infrastructure behind the LeadsFactory web app and API. If the search fails on the LeadsFactory side, the run fails with a named error instead of returning an empty dataset as succeeded.

### Try it before you trust it

- **Smallest real test: $0.41.** Run it on one account where you already know who the Head of Sales is, and check our match and its `score_reason` against yours.
- **Support:** issues on this actor are answered by the LeadsFactory engineering team on the Issues tab. Include the run ID.
- **Maintained:** the same engine powers the LeadsFactory web app, REST API and hosted MCP server. This actor is not a side project.

### FAQ

**Do I need a LinkedIn account or a Sales Navigator subscription?**
No. Nothing to connect, no cookies, no browser extension. LeadsFactory runs the search on its own managed accounts.

**Is my LinkedIn account at risk?**
Your account is not used by this actor, so nothing here can get it flagged or restricted.

**Are emails or phone numbers included?**
No. Each row includes `linkedin_url`, which any email-finder accepts as input. See [Getting emails](#getting-emails).

**How is `ai_score` computed, and how often is the top match the right person?**
An LLM compares the contact's current title, headline and role description with the title you searched. 80–100 means the current title is a direct match for what you asked. 61–79 means an adjacent role. Anything at 60 or below is dropped and never delivered or charged. If you only want direct matches, filter the dataset on `ai_score >= 80`. Every row ships with `score_reason` so you can audit the call in one line instead of reopening the profile.

**What does "AI expands the title" mean, and can I turn it off?**
`Head of Sales` also matches `VP Sales`, `Sales Director`, `Chief Revenue Officer` and non-English equivalents. Set `exactJobTitlesOnly` to `true` to match your wording only. A title can also be a short description, e.g. `person in charge of partnerships`.

**Is this a database or a live search?**
Live. Each run searches Sales Navigator when you run it. That is why it takes minutes, and why you get people a static database rebuilt every few months has not indexed yet: recent job changes, small companies, non-US companies.

**Why did a company return no contacts?**
Either nobody at the company matches the title and filters, or the company could not be matched to a LinkedIn page. Check `OUTPUT` for the reason. Try widening `seniorityLevels`, removing `countryCodes`, or turning off `exactJobTitlesOnly`.

**I have 500 companies. How do I run them all?**
Call the actor from the Apify API or an Apify schedule with 50 companies per run. Each run writes its own dataset; merge them on `linkedin_url`. For direct access with higher limits, use the [LeadsFactory API](https://apiv2.leadsfactory.io/docs).

**How do I get the results into Clay, a CRM or a sheet?**
Use the Apify integrations on the run: webhook on finish, Google Sheets, Make, n8n, Zapier, or read the dataset from the API. Clay's Apify integration runs the actor and reads the dataset directly.

**What happens to the company list I submit?**
It is used to run your search. It is not sold or shared with other users. Results live in your Apify dataset, under your account, with your retention settings.

**Where does the data come from, and is it compliant?**
Rows are read from LinkedIn Sales Navigator profile and company fields as they appear to a logged-in Sales Navigator user at the time of the run. We return no email addresses, no phone numbers, and no data you could not see yourself with a Sales Navigator seat. You are the data controller for your outreach and are responsible for GDPR and CCPA obligations, including notice and opt-out.

**Something failed. Where do I ask?**
Open an issue on this actor's Issues tab with the run ID. The LeadsFactory team answers there.

### About LeadsFactory

[LeadsFactory](https://leadsfactory.io) finds the right buyer at every company for outbound teams and agencies. The same engine is available as a web app, a REST API and a hosted MCP server, with Clay and CRM integrations.

- Website: [leadsfactory.io](https://leadsfactory.io)
- API reference: [apiv2.leadsfactory.io/docs](https://apiv2.leadsfactory.io/docs)

# Actor input Schema

## `companyLinkedinUrls` (type: `array`):

LinkedIn company page URLs, one per line, e.g. https://www.linkedin.com/company/stripe/. The most reliable input when you have it: it skips domain resolution entirely. Use it when a domain is ambiguous or the company has several pages.

## `companyDomains` (type: `array`):

Website domains of the companies to search, one per line, e.g. stripe.com. Each domain is matched to its LinkedIn company page automatically; doubtful matches are flagged in the log. Domains and LinkedIn URLs count together towards the 50-company limit. Only companies matched to a LinkedIn page are charged; the others are listed with a reason in OUTPUT.

## `jobTitles` (type: `array`):

1 to 5 titles, one per persona you want at each company, e.g. "Head of Sales". Each title is expanded with synonyms and translations by AI unless "Exact job titles only" is on. A short description also works, e.g. "person in charge of partnerships".

## `maxContactsPerJobTitle` (type: `integer`):

How many of the best-scoring contacts to return for each title at each company (1-25). Each contact delivered is billed as one dataset item.

## `seniorityLevels` (type: `array`):

Keep only contacts at these levels. Leave empty and the seniority implied by each job title is used.

## `countryCodes` (type: `array`):

Keep only contacts located in these countries, e.g. US, FR, DE. Leave empty for worldwide.

## `exactJobTitlesOnly` (type: `boolean`):

Match your titles literally. Turns off AI expansion with synonyms and translations. Fewer results, tighter match.

## `maxWaitMinutes` (type: `integer`):

Stop waiting after this many minutes and keep the contacts found so far. One company takes a few minutes; companies run in parallel. For 50 companies with 2 or more titles, set 60.

## Actor input object example

```json
{
  "companyLinkedinUrls": [
    "https://www.linkedin.com/company/stripe/"
  ],
  "jobTitles": [
    "Head of Sales"
  ],
  "maxContactsPerJobTitle": 3,
  "exactJobTitlesOnly": false,
  "maxWaitMinutes": 30
}
```

# Actor output Schema

## `contacts` (type: `string`):

Dataset with one row per AI-scored contact (name, title, LinkedIn URL, score, company).

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

OUTPUT record: search status, contacts found, companies resolved / skipped, credits, max\_run\_cost\_reached.

# 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 = {
    "companyLinkedinUrls": [
        "https://www.linkedin.com/company/stripe/"
    ],
    "jobTitles": [
        "Head of Sales"
    ],
    "maxContactsPerJobTitle": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("leadsfactory/leadsfactory-lead-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 = {
    "companyLinkedinUrls": ["https://www.linkedin.com/company/stripe/"],
    "jobTitles": ["Head of Sales"],
    "maxContactsPerJobTitle": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("leadsfactory/leadsfactory-lead-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 '{
  "companyLinkedinUrls": [
    "https://www.linkedin.com/company/stripe/"
  ],
  "jobTitles": [
    "Head of Sales"
  ],
  "maxContactsPerJobTitle": 3
}' |
apify call leadsfactory/leadsfactory-lead-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,leadsfactory/leadsfactory-lead-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/mp9uFqRbJvVEgKppL/builds/GU6sjxwmbzUzq2Tdb/openapi.json
