# B2B Lead Scraper: Public Business Emails (`fetch_cat/lead-scraper-apollo-zoominfo-lusha-ppe-scraper`) Actor

Find public businesses and export visibly published emails, phones, websites, and source pages for transparent B2B research and CRM review.

- **URL**: https://apify.com/fetch\_cat/lead-scraper-apollo-zoominfo-lusha-ppe-scraper.md
- **Developed by:** [Hanna Nosova](https://apify.com/fetch_cat) (community)
- **Categories:** Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.59 / 1,000 item processeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## B2B Lead Scraper: Public Business Emails

Build a source-backed B2B prospect list from public business websites. Discover businesses in an OpenStreetMap-bounded city or enrich a list of public website URLs, then export only contact channels visibly published by those businesses.

> This is for public, no-login business research. It does not access Apollo, ZoomInfo, Lusha, private contact databases, or guessed personal email addresses.

### Who is it for?

Sales operations, agencies, recruiters, researchers, and local-business teams that need a reviewable list of public business contact channels before a compliant outreach or market-research workflow. Use it as a **business email scraper** when public-source provenance matters, or as a **lead generation scraper** for bounded local-business research.

### What you get

Default discovery exports only businesses with a visibly published public email, including its source page. Each row also has the business name, website/domain when public data provides it, phone links, explicit linked social profiles, and the exact pages inspected. Optional MX checks report whether the domain publishes MX records; they do not verify inbox ownership or deliverability.

### Input recipes

#### Find Chicago dentists

```json
{
  "sector": "dentist",
  "country": "United States",
  "cities": ["Chicago"],
  "maxLeads": 10,
  "maxPagesPerSite": 2,
  "requireEmail": true,
  "verifyMx": true
}
```

#### Enrich public business websites

```json
{
  "startUrls": [{ "url": "https://www.freshworksdental.com/" }],
  "maxLeads": 1,
  "maxPagesPerSite": 2,
  "requireEmail": false,
  "verifyMx": true
}
```

### Input settings

| Field | Description |
| --- | --- |
| `sector` | OpenStreetMap business tag/value to find, such as `dentist`. |
| `country` and `cities` | Location boundary for public business discovery. The first supplied city is used. |
| `startUrls` | Optional public business websites to process directly instead of discovery. |
| `maxLeads` | Maximum unique business rows to save (1–100). |
| `maxPagesPerSite` | Homepage plus same-site contact, about, or team pages to inspect (1–5). |
| `requireEmail` | **Enabled by default.** Keep only businesses with a visibly published email address. Disable only for public business-directory research where contact availability is optional. |
| `verifyMx` | Check a domain’s MX records; this is not mailbox validation. |
| `customOffset` | Skip discovered records to resume a bounded batch. |

### Output fields

| Field | Meaning |
| --- | --- |
| `companyName`, `website`, `domain` | Public business identity and normalized site hostname. |
| `country`, `sector`, `address` | Discovery context and public OpenStreetMap address data when available. |
| `discoveryUrl` | OpenStreetMap record URL or the supplied public seed URL. |
| `companyEmails` | Deduplicated public emails and the page where each appeared. |
| `primaryEmail` | First public email found. It is populated in the default email-only discovery mode and can be `null` only when `requireEmail` is explicitly disabled. |
| `emailMxStatus` | `mx_present`, `no_mx`, `lookup_failed`, or `not_checked`. |
| `phones` | Public OSM contact values and visible `tel:` links. |
| `socials` | Explicit linked LinkedIn, Facebook, Instagram, and X/Twitter profiles. |
| `pagesScraped`, `scrapedAt` | Public request provenance and extraction timestamp. |

Example record:

```json
{
  "companyName": "Freshworks Dental Studio",
  "domain": "freshworksdental.com",
  "primaryEmail": "team@freshworksdental.com",
  "companyEmails": [{ "email": "team@freshworksdental.com", "sourceUrl": "https://freshworksdental.com/" }],
  "pagesScraped": ["https://freshworksdental.com/"],
  "emailMxStatus": "mx_present"
}
```

### Use cases

- Build a public supplier or local-business outreach list.
- Find published business contact channels for market research.
- Enrich a buyer-owned list of public websites with source-page provenance.
- Export public business data for CRM review, Google Sheets, or compliant outreach.

### Pricing

See the live [Pricing tab](https://apify.com/fetch_cat/lead-scraper-apollo-zoominfo-lusha-ppe-scraper/pricing) for current per-run and per-result rates.

### Tips and limits

- Use direct `startUrls` when you already know the businesses to research.
- The default email-only mode can return fewer rows because many public sites do not publish an email address. Increase the city scope or use a buyer-owned public website list when you need more qualifying businesses.
- The Actor inspects only a bounded number of same-site contact, about, and team pages.
- Availability depends on public source data. Empty optional fields are never inferred.
- Respect website terms, applicable law, and your outreach obligations.

### API usage

#### Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('fetch_cat/lead-scraper-apollo-zoominfo-lusha-ppe-scraper').call({
  sector: 'dentist', country: 'United States', cities: ['Chicago'], maxLeads: 10,
});
console.log((await client.dataset(run.defaultDatasetId).listItems()).items);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient("APIFY_TOKEN")
run = client.actor("fetch_cat/lead-scraper-apollo-zoominfo-lusha-ppe-scraper").call(run_input={"sector": "dentist", "cities": ["Chicago"], "maxLeads": 10})
print(client.dataset(run["defaultDatasetId"]).list_items().items)
```

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/fetch_cat~lead-scraper-apollo-zoominfo-lusha-ppe-scraper/runs?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"sector":"dentist","cities":["Chicago"],"maxLeads":10}'
```

### MCP and automation

Add this Actor as an MCP tool:

```bash
claude mcp add apify -- npx -y @apify/mcp-server
```

```json
{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": ["-y", "@apify/mcp-server"],
      "env": { "APIFY_TOKEN": "${APIFY_TOKEN}" }
    }
  }
}
```

Use `https://mcp.apify.com?tools=fetch_cat/lead-scraper-apollo-zoominfo-lusha-ppe-scraper`.

Example prompts:

- “Find 10 Chicago dentists with a publicly listed email and include source pages.”
- “Enrich these public business websites and return phones, explicit social links, and MX status.”

### FAQ

#### Does it provide Apollo, ZoomInfo, or Lusha data?

No. It uses OpenStreetMap records and public business websites only.

#### Are emails verified?

No. An email is included only when visibly published. `emailMxStatus` checks DNS MX records, not mailbox ownership or deliverability.

#### Why are there fewer results than `maxLeads`?

A city, sector, source availability, deduplication, and `requireEmail` can limit qualifying records.

#### Can I use my own website list?

Yes. Supply public URLs in `startUrls`; this bypasses OpenStreetMap discovery.

#### What data can I export with b2b lead scraper?

Default email-only discovery rows include a visible public email with its source page. Other public fields—website/domain, phones, address, and linked social profiles—are returned when the source provides them and otherwise remain empty rather than inferred. If you explicitly disable `requireEmail`, email fields can also be empty.

#### Can I run B2B Lead Scraper: Public Business Emails through an API, schedule, or MCP client?

Yes. Use the Node.js, Python, or cURL API examples above, schedule the same JSON input in Apify, or add the Actor to an MCP client with the configuration shown above.

#### How much does it cost to use B2B Lead Scraper: Public Business Emails?

Pricing is per run and per exported item. Check the live Pricing tab for the current rate before starting a larger batch.

### Related Actors

- [Google Maps Scraper](https://apify.com/fetch_cat/google-maps-scraper)
- [Google Search Results Scraper](https://apify.com/fetch_cat/google-search-results-scraper)
- [Google People Also Ask Scraper](https://apify.com/fetch_cat/google-people-also-ask-scraper)
- [Google Hotels Scraper](https://apify.com/fetch_cat/google-hotels-scraper)
- [Google Images Scraper](https://apify.com/fetch_cat/google-images-scraper)

### Support

For a reproducible issue, include your non-sensitive input, run URL, and affected public URL in the Actor’s Issues tab.

# Actor input Schema

## `sector` (type: `string`):

Exact OpenStreetMap business tag/value (for example dentist). Used with country and city discovery.

## `country` (type: `string`):

Country used to bound OpenStreetMap city discovery.

## `cities` (type: `array`):

One or more cities to bound discovery. The first city is used in this release.

## `startUrls` (type: `array`):

Optional direct public-site seeds. These use the independent public-site route instead of OpenStreetMap discovery.

## `maxLeads` (type: `integer`):

Hard cap on unique business rows.

## `maxPagesPerSite` (type: `integer`):

Homepage plus same-site contact/about/team pages to inspect.

## `requireEmail` (type: `boolean`):

Enabled by default so lead-discovery rows always include a visibly published public email. Disable only for public business-directory research where contact availability is optional.

## `verifyMx` (type: `boolean`):

Checks whether the business domain has MX records. This is not a mailbox deliverability check.

## `customOffset` (type: `integer`):

Skip this many discovered businesses before processing. Use to resume a bounded batch.

## Actor input object example

```json
{
  "sector": "dentist",
  "country": "United States",
  "cities": [
    "Chicago"
  ],
  "startUrls": [
    {
      "url": "https://www.freshworksdental.com/"
    }
  ],
  "maxLeads": 2,
  "maxPagesPerSite": 2,
  "requireEmail": true,
  "verifyMx": true,
  "customOffset": 0
}
```

# Actor output Schema

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

No description

# 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 = {
    "sector": "dentist",
    "country": "United States",
    "cities": [
        "Chicago"
    ],
    "startUrls": [
        {
            "url": "https://www.freshworksdental.com/"
        }
    ],
    "maxLeads": 2,
    "maxPagesPerSite": 2,
    "requireEmail": true,
    "verifyMx": true,
    "customOffset": 0
};

// Run the Actor and wait for it to finish
const run = await client.actor("fetch_cat/lead-scraper-apollo-zoominfo-lusha-ppe-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 = {
    "sector": "dentist",
    "country": "United States",
    "cities": ["Chicago"],
    "startUrls": [{ "url": "https://www.freshworksdental.com/" }],
    "maxLeads": 2,
    "maxPagesPerSite": 2,
    "requireEmail": True,
    "verifyMx": True,
    "customOffset": 0,
}

# Run the Actor and wait for it to finish
run = client.actor("fetch_cat/lead-scraper-apollo-zoominfo-lusha-ppe-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 '{
  "sector": "dentist",
  "country": "United States",
  "cities": [
    "Chicago"
  ],
  "startUrls": [
    {
      "url": "https://www.freshworksdental.com/"
    }
  ],
  "maxLeads": 2,
  "maxPagesPerSite": 2,
  "requireEmail": true,
  "verifyMx": true,
  "customOffset": 0
}' |
apify call fetch_cat/lead-scraper-apollo-zoominfo-lusha-ppe-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fetch_cat/lead-scraper-apollo-zoominfo-lusha-ppe-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/c8ntn2nUrLwf6T5l3/builds/Rm9EhI3vYGmosotHH/openapi.json
