# B2B Lead Scraper — Company Emails, Phones & Tech Stack (`junipr/b2b-lead-scraper`) Actor

Generate public B2B lead records from company websites with emails, phones, social links, tech stack, team signals, job posts, and quality scoring.

- **URL**: https://apify.com/junipr/b2b-lead-scraper.md
- **Developed by:** [junipr](https://apify.com/junipr) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 39 total users, 7 monthly users, 75.6% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 company scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## B2B Lead Scraper — Company Emails, Phones & Tech Stack

Scrape B2B lead data from company websites, LinkedIn company pages, and business directories. Extract emails, phone numbers, tech stack, team members, social media links, company size estimates, and more — all from publicly available data. A modern, pay-per-result alternative to Apollo.io, ZoomInfo, and Hunter.io.

### Why Use This Actor

Apollo.io deprecated its Apify scraper in 2025, leaving 50,000+ users without a replacement. ZoomInfo charges $14,000+/year. Hunter.io and Clearbit require monthly subscriptions even for small volumes. This actor gives you fresh, real-time lead data at $15.00 per 1,000 companies with no subscription, no API keys, and no long-term contracts.

Unlike cached database services, this actor scrapes live data directly from company websites, so you always get the most current contact information, tech stack, and team composition.

| Feature | B2B Lead Scraper | Apollo.io | ZoomInfo | Hunter.io |
|---------|-----------------|-----------|----------|-----------|
| Status | Active | Deprecated | $14K/yr+ | $49/mo+ |
| Pricing | $15.00/1K results | N/A | Enterprise | Per-request |
| Tech stack detection | Built-in | No | Limited | No |
| Real-time data | Yes | Cached | Cached | Cached |

### How to Use

**Zero-config start:** Provide one or more company URLs and the actor handles everything. Three scrape modes are available:

**Company Website Mode** — Provide direct company URLs. The actor crawls the homepage, about, contact, and team pages to extract all available data.

```json
{
  "scrapeMode": "companyWebsite",
  "urls": ["https://stripe.com", "https://notion.so"]
}
```

**LinkedIn Company Mode** — Provide LinkedIn company page URLs (not personal profiles). Extracts follower count, employee count, specialties, and company type from public data.

```json
{
  "scrapeMode": "linkedinCompany",
  "urls": ["https://www.linkedin.com/company/microsoft/"]
}
```

**Directory Mode** — Scrape business directories like Yellow Pages, Yelp, or BBB by category and location.

```json
{
  "scrapeMode": "directory",
  "directorySource": "yellowPages",
  "directoryCategory": "software",
  "directoryLocation": "Austin, TX"
}
```

### Input Configuration

All parameters have sensible defaults — only `urls` (or `searchQuery` for search mode) is needed to get started.

**Quick company lookup:**

```json
{ "scrapeMode": "companyWebsite", "urls": ["https://example.com"] }
```

**Full enrichment with all features:**

```json
{
  "scrapeMode": "companyWebsite",
  "urls": ["https://stripe.com"],
  "extractEmails": true,
  "extractPhones": true,
  "extractSocials": true,
  "extractTeamMembers": true,
  "detectTechStack": true,
  "estimateCompanySize": true,
  "extractJobPostings": true,
  "extractPricing": true
}
```

Key parameters: `scrapeMode`, `urls`, `searchQuery`, `directorySource`, `directoryCategory`, `directoryLocation`, `extractEmails`, `extractPhones`, `extractSocials`, `extractTeamMembers`, `detectTechStack`, `detectEmailPattern`, `estimateCompanySize`, `extractJobPostings`, `extractPricing`, `deduplicateByDomain`, `enrichWithLinkedIn`, `maxConcurrency`, `requestDelay`.

### Output Format

Each company produces a structured JSON object with fields for `domain`, `companyName`, `contact` (emails, phones, email pattern), `socialMedia`, `techStack`, `teamMembers`, `size`, `jobPostings`, `pricing`, `headquarters`, `funding`, `news`, and `meta` (including `dataCompleteness` and `confidenceScore`).

CSV output flattens nested fields for direct import into spreadsheets and CRMs. Map fields to HubSpot, Salesforce, or Pipedrive properties using the structured field names — emails map to contact fields, company name and domain to company records, and social links to custom properties.

### Legal and Ethical Use

This actor only scrapes publicly available data from company websites, LinkedIn company pages (public view), and business directories. It does not scrape LinkedIn personal profiles, password-protected pages, or data behind CAPTCHAs. Personal profile URLs are hard-blocked in code and will return a `PERSONAL_PROFILE_BLOCKED` error.

GDPR/CCPA note: all scraped data is from public sources, but you are responsible for how you use it. Check your local laws before using scraped data for cold outreach, marketing, or lead generation.

### Pricing

Pay-per-event: **$15.00 per 1,000 company results** ($0.015 per company). One company = one billable event, regardless of how many pages are crawled per company. Failed scrapes, duplicates, and blocked personal profiles are not billed.

Apify platform usage pass-through is enabled for proxy/browser resources used by enrichment paths.

| Volume | Cost |
|--------|------|
| 10 companies | $0.15 |
| 200 companies | $3.00 |
| 1,000 companies | $15.00 |
| 10,000 companies | $150.00 |

### Proxy Requirements

This actor uses residential proxies by default because LinkedIn and some directories block datacenter IP addresses. Paid Apify plan users get residential proxy access automatically. Free-plan users can provide their own residential proxy URL in the Proxy Configuration input field. Without a residential proxy, LinkedIn enrichment may fail but company website scraping will still work.

### FAQ

#### Is this legal?

Yes. This actor only scrapes publicly available data — the same information anyone can see by visiting a company's website or LinkedIn company page. Court precedent (hiQ Labs v. LinkedIn) supports scraping public data.

#### Can it scrape LinkedIn profiles?

No. LinkedIn personal profiles are hard-blocked in the code. Only LinkedIn company pages (public view) are scraped. Attempting to provide a personal profile URL will return a `PERSONAL_PROFILE_BLOCKED` error.

#### How accurate are the emails?

Emails are extracted directly from company websites and verified against the domain. The `confidence` score on each email indicates reliability. Enable `verifyEmails` for SMTP-level verification (slower but more thorough).

#### Does it verify email addresses?

Optional SMTP verification is available by setting `verifyEmails: true`. This checks if the email server accepts the address. Note that SMTP verification is slower and some mail servers block verification attempts.

#### How does tech stack detection work?

The actor analyzes HTML source code, HTTP headers, meta tags, and script includes to identify technologies. It detects analytics tools (Google Analytics, Segment, Mixpanel), CMS platforms (WordPress, Webflow), frameworks (React, Next.js, Vue), CDNs (Cloudflare, Fastly), payment processors (Stripe, PayPal), and more.

#### Can I use this for cold email outreach?

The actor extracts publicly available email addresses. Whether you can use them for outreach depends on your jurisdiction. Always comply with CAN-SPAM, GDPR, and local regulations. We recommend permission-based outreach.

#### How does it compare to Apollo.io?

Apollo.io's Apify scraper was deprecated in 2025. This actor provides the same core functionality (email discovery, company data, lead generation) with additional features like tech stack detection and real-time scraping at a fraction of the cost. Apollo relied on a cached database; this actor scrapes live data.

#### Can I import results into my CRM?

Yes. JSON output includes structured fields that map directly to CRM properties. Use CSV output for spreadsheet import. For HubSpot, map `companyName` to Company Name, `contact.emails` to Email, `contact.phones` to Phone, and `domain` to Website. Salesforce and Pipedrive follow similar mappings.

# Actor input Schema

## `scrapeMode` (type: `string`):

What to scrape. 'companyWebsite' scrapes provided company URLs. 'linkedinCompany' scrapes LinkedIn company pages. 'directory' scrapes business directories. 'search' discovers companies via search queries.

## `urls` (type: `array`):

Company website URLs or LinkedIn company page URLs. Required for companyWebsite and linkedinCompany modes.

## `searchQuery` (type: `string`):

Search query for finding companies. Required for search mode. E.g., 'SaaS companies in Austin Texas'.

## `directorySource` (type: `string`):

Business directory to scrape. Required for directory mode.

## `industry` (type: `array`):

Industry filters for search mode. E.g., SaaS, fintech, healthcare.

## `location` (type: `string`):

Geographic filter for search mode. E.g., 'Austin, TX', 'United Kingdom', 'California'.

## `companySize` (type: `string`):

Filter by employee count range.

## `fundingStage` (type: `string`):

Filter by funding stage.

## `maxCompanies` (type: `integer`):

Maximum number of companies to find in search or directory mode.

## `directoryCategory` (type: `string`):

Category within the directory. E.g., restaurants, plumbers, software.

## `directoryLocation` (type: `string`):

Location filter for directory search.

## `directoryMaxResults` (type: `integer`):

Maximum results from directory scrape.

## `extractEmails` (type: `boolean`):

Find email addresses on company websites.

## `extractPhones` (type: `boolean`):

Find phone numbers on company websites.

## `extractSocials` (type: `boolean`):

Find social media profile links.

## `extractTeamMembers` (type: `boolean`):

Find team member names and titles from public about/team pages.

## `maxTeamMembers` (type: `integer`):

Maximum team members to extract per company.

## `detectEmailPattern` (type: `boolean`):

Analyze found emails to detect the company's email naming pattern (e.g., firstname@, first.last@).

## `verifyEmails` (type: `boolean`):

Verify email addresses via SMTP check. Slower and may trigger spam filters on the target mail server.

## `detectTechStack` (type: `boolean`):

Detect technologies used by company websites (analytics, CMS, frameworks, hosting, CDN, etc.).

## `techCategories` (type: `array`):

Technology categories to detect. Options: all, analytics, cms, ecommerce, framework, hosting, marketing, payment, security, cdn.

## `estimateCompanySize` (type: `boolean`):

Estimate employee count from various signals on the website.

## `extractJobPostings` (type: `boolean`):

Check for open job postings as a company growth signal.

## `maxJobPostings` (type: `integer`):

Maximum job postings to extract per company.

## `extractPressReleases` (type: `boolean`):

Look for recent news and press releases on the company site.

## `extractPricing` (type: `boolean`):

Attempt to find pricing page information.

## `outputFormat` (type: `string`):

Output format for results.

## `deduplicateByDomain` (type: `boolean`):

Prevent duplicate entries for the same domain.

## `enrichWithLinkedIn` (type: `boolean`):

After scraping company website, also check LinkedIn company page for additional data. Adds ~3s per company.

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

Residential proxy recommended for LinkedIn scraping. Defaults to Apify residential proxy (requires paid Apify plan). Free-plan users can provide their own residential proxy URL.

## `requestDelay` (type: `integer`):

Minimum delay between requests to the same domain in milliseconds.

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

Maximum concurrent requests.

## `maxRetries` (type: `integer`):

Retry failed requests up to this many times.

## Actor input object example

```json
{
  "scrapeMode": "companyWebsite",
  "urls": [
    "https://stripe.com"
  ],
  "searchQuery": "",
  "directorySource": "yellowPages",
  "industry": [],
  "location": "",
  "companySize": "",
  "fundingStage": "",
  "maxCompanies": 1,
  "directoryCategory": "",
  "directoryLocation": "",
  "directoryMaxResults": 1,
  "extractEmails": true,
  "extractPhones": true,
  "extractSocials": true,
  "extractTeamMembers": false,
  "maxTeamMembers": 5,
  "detectEmailPattern": true,
  "verifyEmails": false,
  "detectTechStack": false,
  "techCategories": [
    "all"
  ],
  "estimateCompanySize": false,
  "extractJobPostings": false,
  "maxJobPostings": 5,
  "extractPressReleases": false,
  "extractPricing": false,
  "outputFormat": "json",
  "deduplicateByDomain": true,
  "enrichWithLinkedIn": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "requestDelay": 2000,
  "maxConcurrency": 1,
  "maxRetries": 2
}
```

# Actor output Schema

## `results` (type: `string`):

Extracted B2B lead data per company: emails, phones, tech stack, team members, social links, company size, and more.

# 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 = {
    "urls": [
        "https://stripe.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("junipr/b2b-lead-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 = {
    "urls": ["https://stripe.com"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("junipr/b2b-lead-scraper").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 '{
  "urls": [
    "https://stripe.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call junipr/b2b-lead-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=junipr/b2b-lead-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/LcBnFBEz71wp1nGJs/builds/j7ZuWAOxsysaVkuD0/openapi.json
