# LinkedIn B2B Phone Number Scraper (`maximedupre/linkedin-b2b-phone-number-scraper`) Actor

Find phone numbers and business emails visible in public LinkedIn content. Target B2B terms or public profile and company URLs, then save structured leads with source links, contact status, and normalized phone numbers when available.

- **URL**: https://apify.com/maximedupre/linkedin-b2b-phone-number-scraper.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Lead generation, Social media, Business
- **Stats:** 1 total users, 1 monthly users, 70.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.65 / 1,000 phone leads

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

### 📞 Find public LinkedIn B2B contact leads

Sales teams, recruiters, and researchers can search public LinkedIn content for B2B leads. Each saved row can include source context, contact availability, and any phone number or business email visible in that source. Phone numbers pass country-aware validation and normalization, so you can review public contact data in one structured dataset.

- Find phone numbers and public contact details for **[Accounting Firms](https://apify.com/maximedupre/linkedin-b2b-phone-number-scraper/examples/accounting-firms)**.
- Build a public lead list for **[Staffing Agencies](https://apify.com/maximedupre/linkedin-b2b-phone-number-scraper/examples/staffing-agencies)**.
- Research **[Marketing Agencies](https://apify.com/maximedupre/linkedin-b2b-phone-number-scraper/examples/marketing-agencies)** with B2B terms and source links.
- Filter **[SaaS Companies](https://apify.com/maximedupre/linkedin-b2b-phone-number-scraper/examples/saas-companies)** leads by phone and email availability.
- Collect source-backed leads for **[Software Companies](https://apify.com/maximedupre/linkedin-b2b-phone-number-scraper/examples/software-companies)** in one run.

#### 📋 Public LinkedIn lead records

Each dataset row is one eligible lead from public LinkedIn content. It can include a name, title, source type, matched target, public source URL, description, location, phone number, business email, contact flags, contact status, and collection time. If the same source item matches again through another target, only its first eligible match is saved.

#### ▶️ Run a public LinkedIn search

Choose one target type for each run: B2B terms, public profile URLs, or public company URLs. The other target fields stay visible but are ignored. The selected targets share the same geography, source type, exclusion, contact, and lead limit settings.

**Run steps**

1. Choose `terms`, `profileUrls`, or `companyUrls` in `target`.
2. Add B2B terms or public LinkedIn URLs to the matching target field.
3. Add optional filters for geography, source type, excluded terms, and contact completeness.
4. Start the run and open the default dataset to review the saved leads.

#### ⚙️ Input

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `target` | string | Choose `terms`, `profileUrls`, or `companyUrls`. Only the chosen target list is used. |
| `searchTerms` | array of strings | B2B terms to search. Each term uses the same filters in this run. |
| `sourceTypes` | array of strings | Optional source types for B2B terms: `people`, `profiles`, `companies`, or `postsPages`. Leave empty to use all types. Direct URL targets set their source type. |
| `profileUrls` | array of objects | Public LinkedIn profile URLs. Each object has a `url` value. All URLs use the same filters. |
| `companyUrls` | array of objects | Public LinkedIn company URLs. Each object has a `url` value. All URLs use the same filters. |
| `geography` | string | Optional place or country code for search and phone number checks. |
| `excludeTerms` | array of strings | Optional words to skip when they appear in visible lead context. Each term applies to every target. |
| `requireCompleteContact` | boolean | When `true`, keep only leads with both a phone number and a business email. When `false`, keep leads with either one. |
| `maxItems` | integer | Optional run limit. Stop after this many leads. Leave empty to return all available results until the public source is exhausted. |

**Lead limit**

Leave `maxItems` empty to return all available results until the public source is exhausted. Set a small number when you need a smaller first run.

**Example input**

This example is copied from a successful current-beta terms run.

```json
{
  "target": "terms",
  "searchTerms": [
    "software companies"
  ],
  "requireCompleteContact": false,
  "maxItems": 25
}
```

#### 🧾 Output

The output schema links to the default dataset. There is one row shape, and optional text and contact fields appear only when the public source exposes them.

**Lead fields**

| Field | Type | What it does |
| --- | --- | --- |
| `sourceType` | string | Public LinkedIn source type: `people`, `profiles`, `companies`, or `postsPages`. |
| `matchedTarget` | string | The term or public URL that found the lead. |
| `sourceUrl` | string (URL) | Public LinkedIn URL for the source that contains the lead. |
| `name` | string | Name shown for the lead, when available. |
| `title` | string | Public title shown for the lead, when available. |
| `description` | string | Public description or summary for the lead, when available. |
| `location` | string | Public location shown for the lead, when available. |
| `phoneNumber` | string | A phone number visible in the source after country-aware validation and normalization, when available. |
| `businessEmail` | string (email) | A business email visible in the same public source, when available. |
| `phoneAvailable` | boolean | Whether a validated public phone number is available for the lead. |
| `emailAvailable` | boolean | Whether a public business email is available for the lead. |
| `contactStatus` | string | Contact state: `complete`, `phoneOnly`, `emailOnly`, or `noContact`. |
| `collectedAt` | string (date-time) | Time when the lead was found in public results. |

**Example lead**

This complete row came from a successful current-beta run. The public source values are shown without shortening.

```json
{
  "sourceType": "companies",
  "matchedTarget": "info@iphtechnologies.com",
  "sourceUrl": "https://in.linkedin.com/company/iph-technologies",
  "phoneAvailable": true,
  "emailAvailable": true,
  "contactStatus": "complete",
  "collectedAt": "2026-08-25T20:29:52.786Z",
  "name": "IPH Technologies",
  "title": "IPH Technologies - A Software & Mobile App Development ...",
  "description": "... info@iphtechnologies.com Skype: lekha.mishra Call: Los Angeles, CA, United States: +1 213 7882911 | India: +91522 4958245. Website: https://iphtechnologies ...Read more",
  "location": "United States",
  "phoneNumber": "+12137882911",
  "businessEmail": "info@iphtechnologies.com"
}
```

#### 💳 Pricing

**Charged event**

This Actor has one buyer-facing event, `Phone lead`, priced at `$0.00265` for one saved lead with a publicly visible phone number that passed country-aware validation and includes source context. It does not promise that every lead has a phone number or email. A run that saves no qualifying lead has no Actor-owned lead event to bill. Apify platform usage may still apply.

#### 🔌 Integrations

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

Open the default dataset in Apify after a run or retrieve its structured rows through the Apify API. Use the public source URL in each row when you need to review the source.

#### ❓ FAQ

##### Can I use a public LinkedIn profile or company URL?

Yes. Select `profileUrls` or `companyUrls` and add public URLs. A direct URL target sets its source type.

##### Does the Actor use my LinkedIn account?

No. It searches publicly available, non-login-gated LinkedIn content and does not require a buyer's LinkedIn account or source login.

##### What happens when the same source appears twice?

The Actor saves the first eligible occurrence and ignores later matches for that source item, even when another term or target finds it.

##### Can I require both a phone and a business email?

Yes. Turn on `requireCompleteContact` to keep only leads with both. When it is off, leads with either one can remain in the dataset.

##### What if a public source has no phone number?

The row can still be saved when it meets the other filters. `phoneAvailable` is `false`, and `contactStatus` shows `emailOnly` or `noContact`. The Actor does not guess phone numbers.

##### Can one run use different filters for different targets?

No. Pick one target type for a run. All values in that target use the same filters.

##### What does an empty Lead limit do?

It returns all available results until the public source is exhausted. Use a small integer for a smaller run.

##### What does contactStatus mean?

`complete` means both a phone number and a business email are present. `phoneOnly` means only a phone is present. `emailOnly` means only an email is present. `noContact` means neither is present.

### 📝 Changelog

**0.0: Initial release**

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~linkedin-b2b-phone-number-scraper/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [LinkedIn Company Scraper](https://apify.com/maximedupre/linkedin-company-scraper): Add public company profile context such as industries, sizes, locations, and source URLs.
- [LinkedIn Company People Scraper](https://apify.com/maximedupre/linkedin-company-people-scraper): Map visible people and roles for a known LinkedIn company before reviewing lead rows.
- [Website Emails Scraper](https://apify.com/maximedupre/website-emails-scraper): Find public email addresses on company websites linked from your lead research.
- [Google Maps Phone Number Scraper](https://apify.com/maximedupre/google-maps-phone-number-scraper): Find public business phone numbers from Google Maps when a LinkedIn source has no contact number.
- [Phone Number Validation API](https://apify.com/maximedupre/phone-number-validation): Check and format phone numbers after you collect them from public sources.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `target` (type: `string`):

Choose one target for this run.

## `searchTerms` (type: `array`):

Add one or more B2B terms. Each term uses the same filters in this run.

## `sourceTypes` (type: `array`):

Optional public LinkedIn source types for B2B terms. Leave this list empty to use all types. Direct URL targets set their source type.

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

Add one or more public LinkedIn profile URLs. Each URL uses the same filters in this run.

## `companyUrls` (type: `array`):

Add one or more public LinkedIn company URLs. Each URL uses the same filters in this run.

## `geography` (type: `string`):

Optional place or country code for search and phone number checks. Example: United States.

## `excludeTerms` (type: `array`):

Optional words to skip when they appear in visible lead context. Each term applies to every target.

## `requireCompleteContact` (type: `boolean`):

When on, return only leads with both a phone number and a business email. When off, keep leads with either one.

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

Optional run limit. Stop after this many leads. Leave empty to collect available leads until the public source is exhausted.

## Actor input object example

```json
{
  "target": "terms",
  "searchTerms": [
    "software companies"
  ],
  "profileUrls": [
    {
      "url": "https://www.linkedin.com/in/jane-doe"
    }
  ],
  "companyUrls": [
    {
      "url": "https://www.linkedin.com/company/acme"
    }
  ],
  "geography": "United States",
  "requireCompleteContact": false,
  "maxItems": 25
}
```

# Actor output Schema

## `dataset` (type: `string`):

Structured lead records from this 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 = {
    "target": "terms",
    "searchTerms": [
        "software companies"
    ],
    "maxItems": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/linkedin-b2b-phone-number-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 = {
    "target": "terms",
    "searchTerms": ["software companies"],
    "maxItems": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/linkedin-b2b-phone-number-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 '{
  "target": "terms",
  "searchTerms": [
    "software companies"
  ],
  "maxItems": 25
}' |
apify call maximedupre/linkedin-b2b-phone-number-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/linkedin-b2b-phone-number-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/lEVkNwehW2QQUW1Ks/builds/N9RNeWBMSACfaqSMs/openapi.json
