# B2B Lead Scraper - Emails, Phones & Lead Scoring (`invincible_brookbed/b2b-lead-gen-pro`) Actor

Turn company domains into sales-ready B2B leads: emails, phones, decision-makers, tech stack and a transparent 0-100 lead score. Pay only for leads that pass your quality gate. No LinkedIn scraping. MCP-ready for AI agents.

- **URL**: https://apify.com/invincible_brookbed/b2b-lead-gen-pro.md
- **Developed by:** [Виталий Белогуров](https://apify.com/invincible_brookbed) (community)
- **Categories:** Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 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?

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

## B2B Lead Scraper — Company Email Finder & Lead Scoring

**B2B lead scraper and company email finder from websites.** Give this Actor company domains and it returns emails, phone numbers, decision-makers with seniority, social profiles, tech stack and a **transparent 0–100 lead score** — all from public website data, with no database subscription and no LinkedIn scraping.

If you want Apollo-style company enrichment without a per-seat contract, this is a pay-per-lead alternative: you only pay for leads that pass your quality gate (~**$30 per 1,000 leads** at the promotional rate).

### What you get for every company

| Data | Details |
|---|---|
| **Company profile** | Name (from JSON-LD / Open Graph / title), description, logo, address, founding date, employee count when published |
| **Emails** | Published addresses classified as `personal` or `generic` (info@, sales@…), on-domain flag, **MX record check** |
| **Email pattern** | Detected naming convention such as `{first}.{last}@company.com`, with a confidence value |
| **Phones** | International-format numbers from `tel:` links and page text |
| **Decision-makers** | Name, title and **seniority: C-level / VP / Director / Manager / Other**, plus direct email and LinkedIn profile when the site lists them |
| **Social links** | Company LinkedIn, Twitter/X and Facebook pages |
| **Tech stack** | 75+ technologies detected from HTML, scripts and HTTP headers: CMS, e-commerce, CRM, marketing automation, analytics, live chat, CDN, hosting |
| **Lead score** | `leadScore` 0–100 and a full `leadScoreBreakdown` that shows every point |
| **Metadata** | `scrapedAt` ISO timestamp, pages crawled, PII mode flag |

> **Honest by design.** The Actor only reads what companies publish on their own websites. It does not scrape LinkedIn, does not buy or fake employee databases, and does not invent email addresses. If a site lists no team, you get no contacts — and a lower score that says so.

### Why this Actor beats typical lead scrapers

- **Transparent scoring.** You see *why* a lead scored 72. Seven components (email quality, deliverability, phone, decision-makers, social, company profile, tech stack) each report their points and signals.
- **Quality gate.** Set `minLeadScore` and weak leads are dropped before they are charged.
- **Incremental runs.** Schedule weekly runs on the same list; domains enriched within `incrementalFreshnessDays` are skipped, so you pay only for new or stale companies.
- **Deliverability signal.** Every company domain gets a DNS MX lookup, so you can filter out dead domains before they hit your CRM.
- **Privacy option.** `piiSafeMode` replaces emails and phone numbers with deterministic SHA-256 hashes — handy for matching against your own hashed lists, analytics, or compliance reviews.
- **Webhook delivery.** Push enriched leads straight into your CRM, Zapier, Make or n8n flow.
- **Clean input handling.** Paste domains, full URLs, `www.` hosts or even email addresses; they are normalized and de-duplicated automatically.

### How the lead score works

`leadScore = round(100 × pointsEarned ÷ pointsAvailable)`

| Component | Max points | Examples of signals |
|---|---|---|
| Email quality | 20 | any email, email on company domain, named email, pattern detected |
| Email deliverability | 10 | company domain publishes MX records |
| Phone | 10 | phone found, extra / direct number |
| Decision-makers | 25 | named contact with title, C-level (10) / VP (8) / Director (6) / Manager (3), direct email or LinkedIn |
| Social | 14 | LinkedIn company page (8), Twitter/X (3), Facebook (3) |
| Company profile | 12 | name, description, address, JSON-LD organization data |
| Tech stack | 9 | technologies detected, business-relevant tools |

If you switch an enrichment module off (for example `enrichTechStack: false`), its points are removed from the denominator, so scores stay comparable and your `minLeadScore` keeps working. Every record contains `leadScoreBreakdown.components.*.signals` listing the exact `+N` reasons.

### Input

| Field | Description |
|---|---|
| `companies` | Domains or URLs, one per line (required) |
| `maxResults` | Stop after this many delivered leads (default 100) |
| `maxContactsPerCompany` | Contacts returned per company, 0 disables contact extraction (default 5) |
| `minLeadScore` | Quality gate 0–100; lower-scoring leads are dropped and not charged |
| `enrichEmails` / `enrichSocial` / `enrichTechStack` | Toggle modules |
| `skipSocialEnrichment` | Hard override that disables social extraction |
| `incrementalMode`, `incrementalFreshnessDays` | Skip recently enriched domains |
| `webhookUrl` | POST results to your endpoint |
| `piiSafeMode` | Hash emails and phones |
| `proxyConfiguration` | Optional; **off by default**. Enable only for large lists / rate limits. No captcha needed. |

Ready-to-use example: [`examples/input.json`](examples/input.json).

### Example output

```json
{
  "domain": "acme-industrial.com",
  "website": "https://www.acme-industrial.com/",
  "companyName": "Acme Industrial",
  "emails": [
    { "value": "jane.doe@acme-industrial.com", "type": "personal", "domain": "acme-industrial.com", "onCompanyDomain": true, "mxValid": true, "hashed": false }
  ],
  "emailPattern": { "pattern": "{first}.{last}", "exampleTemplate": "{first}.{last}@acme-industrial.com", "confidence": 0.8, "sampleSize": 3, "basis": "named-contacts" },
  "phones": ["+15551234567"],
  "contacts": [
    { "name": "Jane Doe", "title": "Chief Executive Officer", "seniority": "C-level", "isDecisionMaker": true, "linkedinUrl": "https://www.linkedin.com/in/janedoe" }
  ],
  "social": { "linkedin": "https://www.linkedin.com/company/acme-industrial", "twitter": null, "facebook": null },
  "techStack": [{ "name": "HubSpot", "category": "Marketing automation" }],
  "leadScore": 82,
  "scrapedAt": "2026-10-11T09:30:00.000Z"
}
```

### Pricing

**Pay-per-event** pricing:

| Event | Price | When it is charged |
|---|---|---|
| `lead-enriched` | **$0.03** (about **$30 per 1,000** qualified leads) | One lead delivered to your dataset |

Leads below `minLeadScore`, unreachable websites, skipped incremental domains and invalid records are **never** charged. If your maximum cost per run is reached, the Actor stops cleanly. Use `minLeadScore` (40–60 recommended for outreach) so you only pay for usable contacts.

### Common use cases

- **Outbound sales and SDR teams** — build account lists with contacts and a score to prioritize outreach.
- **Agencies** — qualify prospects by tech stack ("uses Shopify, no analytics") and decision-maker availability.
- **CRM hygiene** — refresh stale company records on a schedule with incremental mode.
- **Market research** — map technology adoption across a list of competitors or customers.
- **Marketing ops** — enrich inbound signups by domain and route high scorers to sales.

### Tips for best results

1. Use `minLeadScore` between 40 and 60 for outreach lists.
2. Enable Apify Proxy for lists above a few hundred domains.
3. Schedule runs with `incrementalMode` for monitoring.
4. Combine `piiSafeMode` with a webhook when you only need hashed identifiers downstream.
5. Pages that render team members only with JavaScript will yield fewer contacts; the score reflects that.

### Limits and good practice

- Data comes only from the company's own public pages (homepage plus contact, about and team pages when linked).
- Contact detection is heuristic. Always sample-check before large campaigns.
- Email addresses are not verified by sending mail; the MX check confirms the domain can receive mail, not that a mailbox exists.
- You are responsible for lawful use of the data, including GDPR, CAN-SPAM and local B2B marketing rules. `piiSafeMode` helps limit exposure of personal data.

### Integrations

Export results as JSON, CSV, Excel or via the Apify API, or connect with Zapier, Make, n8n, Google Sheets and HubSpot. The webhook receives `leads.enriched` batches (up to 25 leads) and a final `run.finished` event with run statistics. Statistics are also stored in the key-value store record `RUN_STATS`.

### Use with AI agents (MCP)

Works with the [Apify MCP server](https://mcp.apify.com/):

```json
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com/?tools=fetch-actor-details,call-actor,invincible_brookbed/b2b-lead-gen-pro"
    }
  }
}
```

Authenticate via OAuth or an Apify API token. Your agent can read the input schema and run this Actor with `call-actor`.

### FAQ

**Does it scrape LinkedIn?** No. It only finds the company's LinkedIn page URL linked from its own website.

**Can it find emails that are not published?** No. It reports published addresses and the detected naming pattern; it never guesses or fabricates addresses.

**How does incremental mode remember domains?** In a named key-value store (`b2b-lead-gen-pro-incremental`) in your account, so state survives between runs.

# Actor input Schema

## `companies` (type: `array`):

Company domains or website URLs, one per line. Examples: `stripe.com`, `https://www.notion.so/`, `www.hubspot.com`. Domains are normalized and de-duplicated automatically.

## `maxResults` (type: `integer`):

Maximum number of enriched leads to deliver (and bill). The run stops once this many leads passed the quality gate.

## `maxContactsPerCompany` (type: `integer`):

Maximum number of named decision-makers / contacts returned per company (most senior first). Set to 0 to skip contact extraction entirely.

## `minLeadScore` (type: `integer`):

Leads scoring below this value (0-100) are dropped and NOT charged. Use 40-60 to keep only well-enriched leads.

## `enrichEmails` (type: `boolean`):

Extract published email addresses, classify them (personal / generic), detect the company's email naming pattern and verify MX records via DNS.

## `enrichSocial` (type: `boolean`):

Find the company's LinkedIn, Twitter/X and Facebook pages from the website.

## `enrichTechStack` (type: `boolean`):

Detect CMS, e-commerce, analytics, marketing, CRM, chat and hosting technologies from HTML and HTTP headers.

## `incrementalMode` (type: `boolean`):

Skip domains that were already enriched (and delivered) within the freshness window, so scheduled runs only pay for new or stale leads. State is kept in the named key-value store `b2b-lead-gen-pro-incremental`.

## `incrementalFreshnessDays` (type: `integer`):

In incremental mode, domains enriched within this many days are skipped.

## `skipSocialEnrichment` (type: `boolean`):

Force-disable social link extraction even if 'Extract social links' is on. Social points are then excluded from the lead score.

## `webhookUrl` (type: `string`):

Optional. Enriched leads are POSTed here as JSON batches (`event: leads.enriched`, up to 25 leads each), followed by a final `run.finished` event. Failures are retried and never fail the run.

## `piiSafeMode` (type: `boolean`):

Replace all email addresses and phone numbers with SHA-256 hashes in the output and webhook payloads. Hashes are deterministic, so you can still de-duplicate or match against your own hashed lists.

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

Optional. Off by default — most company sites work without a proxy. Enable Apify Proxy only for large lists or when you hit rate limits. Captcha solving is not required.

## Actor input object example

```json
{
  "companies": [
    "apify.com",
    "hubspot.com",
    "notion.so"
  ],
  "maxResults": 100,
  "maxContactsPerCompany": 5,
  "minLeadScore": 0,
  "enrichEmails": true,
  "enrichSocial": true,
  "enrichTechStack": true,
  "incrementalMode": false,
  "incrementalFreshnessDays": 30,
  "skipSocialEnrichment": false,
  "piiSafeMode": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `leads` (type: `string`):

Full JSON for every enriched company: contacts, emails, phones, social, tech stack, lead score.

## `overview` (type: `string`):

Compact table view for quick review in Console (company, score, emails, contacts).

## `runStats` (type: `string`):

Counts of processed/delivered/skipped/failed domains, charged events, and duration.

# 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 = {
    "companies": [
        "apify.com",
        "hubspot.com",
        "notion.so"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("invincible_brookbed/b2b-lead-gen-pro").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 = {
    "companies": [
        "apify.com",
        "hubspot.com",
        "notion.so",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("invincible_brookbed/b2b-lead-gen-pro").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 '{
  "companies": [
    "apify.com",
    "hubspot.com",
    "notion.so"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call invincible_brookbed/b2b-lead-gen-pro --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,invincible_brookbed/b2b-lead-gen-pro"
        }
    }
}
```

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/eMdE3KHXbc6bdDJZN/builds/FlSeub0V0Jm0pIDFg/openapi.json
