# Local Business Email Finder – Owner Emails, Phones & Socials (`inovaflow/local-business-email-finder`) Actor

Find the owner's or business e-mail of any local business — from a list of names or websites, or a search by category and city. Deep website crawl + long-tail web search, owner name and title, phones and socials; every e-mail verified and tagged with source and confidence. Dataset-only, MCP-ready.

- **URL**: https://apify.com/inovaflow/local-business-email-finder.md
- **Developed by:** [inovaflow](https://apify.com/inovaflow) (community)
- **Categories:** Lead generation, AI
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 email 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 the owner's or business e-mail of any local business — and get back a lead you can actually write to.** Give it businesses (names with a city, or websites) or a search (a category and a location), and every business comes back with its **e-mail addresses** — owner, personal and generic — each **verified** and tagged with **where it was found** and how confident the match is, plus the **owner's name and title**, phone numbers and social profiles.

If you sell to local businesses, your prospect list is easy: every dentist, roofer, gym, café and law firm in a city is listed with a phone and a website. What the listings never give you is the e-mail — and the owner's address is rarely on the home page. It sits on the contact or team page, in the site's imprint, on an association directory, in a local news piece, on page 19 of a web search. This Actor does that digging for you, business by business, and shows its work.

### Local business email finder: what you get

One row per business:

| Field | What it tells you |
| --- | --- |
| `emails[]` | Every address found: `address`, `type` (`owner` / `personal` / `generic`), `source` (the page or search it came from), `sourceUrl`, `confidence` (0–100), `verified`, `verification` method, `personName` |
| `primaryEmail`, `ownerEmail`, `emailCount` | The address to use, the owner's address when found, and how many there are |
| `ownerName`, `ownerTitle`, `ownerSource`, `people[]` | The owner / founder / principal / practice owner and other named contacts, with where each was found |
| `phones[]`, `socials{}` | Phone numbers from the listing and the website; Facebook, Instagram, LinkedIn, X, YouTube, TikTok, Pinterest, WhatsApp |
| `name`, `category`, `address`, `city`, `postalCode`, `state`, `countryCode`, `website`, `domain`, `googleMapsUrl`, `rating`, `reviewsCount` | The business identity, ready for a CRM |
| `status` | `found`, `no_email`, `no_website`, `unreachable` — so an agent can tell "nothing there" from "could not check" |
| `contactPageUrl`, `pagesCrawled`, `searchQueriesRun`, `sources[]` | The audit trail |

The **Leads** view is the one-line-per-business table; **E-mails with evidence** shows every address with its source; **Owners** lists the businesses where a person was identified.

### How the e-mails are found

1. **Deep website crawl** — the home page and the contact, about, team, staff, imprint and legal pages (linked or at their usual paths), reading `mailto:` links, plain text, structured data, and the obfuscated forms sites use to hide addresses from bots (Cloudflare e-mail protection, HTML entities, `name [at] domain`, script-built addresses).
2. **Long-tail web search** — searches for the business and its domain; e-mails in result snippets are read for free, and the top result pages (directories, associations, chambers, local press) are fetched and mined. An off-site address is attributed only when its domain matches the business website or the business name sits next to it.
3. **Owner identification** — names next to titles ("Jane Doe, Owner", "Practice owner: …", "Inhaber: …", "Dr. … DDS", "founded by …") on the website and in search results.
4. **Classification** — an address that matches the owner's name is `owner`; a person's name is `personal`; `info@`/`office@`/`hello@` is `generic`.
5. **Verification** — syntax, then the domain's mail server, then an SMTP mailbox check with catch-all detection. `verified` is true only when the mail server confirmed the mailbox; the method is always reported (`smtp-valid`, `smtp-catch-all`, `mx-only`, `syntax-only`). Undeliverable addresses are dropped.

Optionally, when the owner's name is known but no owner mailbox was found, likely addresses on the business domain are generated and kept only if the mailbox check confirms them (**Include pattern-guessed owner e-mails**, off by default).

### Two ways in

- **A list** — business names with a city (`Beyond Wow Plumbing, Austin TX`), websites (`reliantplumbing.com`), or a mix. Names are matched to their listing to pick up the website, phone, address and rating; websites go straight to the crawl.
- **A search** — `dentists` + `Boulder, CO`, `roofing contractors` + `Manchester, UK`. Businesses are discovered by category and location and each one is enriched.

### Who uses it

- **Agencies & freelancers** — every restaurant, clinic or contractor in town with an e-mail to pitch, and the owner's name for the first line.
- **Sales teams** — territory prospecting by category and city, straight into a sequence, with verification already done.
- **Local marketers, event and partnership teams** — reachable lists for outreach and directories.
- **Data teams** — a contact-enrichment step for an existing business list (pass the websites), with a source and confidence per address.
- **AI agents** — a keyword-discoverable, MCP-callable tool that runs unattended and returns a clean, typed dataset.

### Set it up in a minute

1. Paste **Businesses** (one per line: name + city, or a website) — or enter **search queries** and a **Location**.
2. Start. Rows arrive as each business is finished.

Advanced settings (collapsed) control crawl depth, web-search depth, verification, pattern guessing, country/language, concurrency and proxy. The defaults are tuned for unattended runs.

### Use it from an agent or the API

```json
{ "businesses": ["Beyond Wow Plumbing & Drains, Austin TX", "reliantplumbing.com"] }
```

```json
{ "searchQueries": ["dentists"], "location": "Boulder, CO", "maxPlacesPerQuery": 50, "onlyWithEmail": true }
```

Agents may also pass `domains`, `websites` or `urls`, or objects `{ "name": "...", "location": "...", "website": "..." }`. Results are in the default dataset (`?view=leads`, `?view=emails`, `?view=owners`); a run summary is in the `OUTPUT` record of the run's key-value store. Through the Apify MCP server, call `inovaflow/local-business-email-finder` with the same input.

### Output example

```json
{
  "name": "Boulder Dental Center",
  "category": "Dentist",
  "address": "1234 Arapahoe Ave, Boulder, CO 80302",
  "phone": "(303) 555-0142",
  "website": "https://www.boulderdentalcenter.com/",
  "domain": "boulderdentalcenter.com",
  "status": "found",
  "primaryEmail": "patient@boulderdentalcenter.com",
  "ownerEmail": "drsmith@boulderdentalcenter.com",
  "ownerName": "Dr. Jane Smith",
  "ownerTitle": "Dentist",
  "emails": [
    { "address": "drsmith@boulderdentalcenter.com", "type": "owner", "source": "website:/our-team", "sourceUrl": "https://www.boulderdentalcenter.com/our-team", "confidence": 100, "verified": true, "verification": "smtp-valid", "personName": "Dr. Jane Smith" },
    { "address": "patient@boulderdentalcenter.com", "type": "generic", "source": "website:/contact", "sourceUrl": "https://www.boulderdentalcenter.com/contact", "confidence": 90, "verified": true, "verification": "smtp-valid", "personName": null }
  ],
  "phones": ["(303) 555-0142"],
  "socials": { "facebook": "https://www.facebook.com/boulderdentalcenter", "instagram": "https://www.instagram.com/boulderdentalcenter", "linkedin": null },
  "pagesCrawled": 5,
  "searchQueriesRun": 3
}
```

### Pricing

Pay only for hits: a small fee per **business delivered with at least one e-mail**. Businesses where no address could be found are delivered free with their phones, socials and status, and so are unreachable websites. A run start fee applies per gigabyte of memory. No subscription, no minimum.

### Coverage and limits

- Works for any country and language; the owner-title vocabulary covers English, German, French, Spanish and Italian forms.
- Only public information is used: the business's own website, public listings and public web pages. Social profiles are collected as links, not crawled.
- Verification confirms what a mail server is willing to confirm: catch-all domains accept any address and are reported as `smtp-catch-all` rather than verified.
- A business without a website gets the search step only; a website that blocks automated access is reported as `unreachable` and is free.

### FAQ

**Why not just scrape the listings?** Listings have no e-mails. The address is on the website's inner pages or elsewhere on the web — that is the work this Actor does, with a source per address so you can trust it.

**Do I get the owner's personal address?** When it is public: named on the site or in a directory and either published or matching the owner's name on the business domain. The `type` field tells you which kind of address you have.

**Are the e-mails verified?** Every address passes syntax and mail-server checks; where the server allows it, the mailbox itself is confirmed. `verified: true` means the mailbox was confirmed.

**Can I pass my own list?** Yes — names with a city, websites, or a mix.

**How fast is it?** Around 10–20 seconds per business including the web search; a 100-business search finishes in a few minutes.

# Actor input Schema

## `businesses` (type: `array`):

One per line: a business name with its city ("Beyond Wow Plumbing, Austin TX") or a website ("reliantplumbing.com"). Names are matched to their listing to get the website, phone and address. Also accepted as `domains`, `websites`, `urls` or objects {name, location, website}.

## `searchQueries` (type: `array`):

Category or keyword searches ("dentists", "roofing contractors", "italian restaurants") — combined with the location below to discover businesses, each of which is then enriched.

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

City, region or country for the searches and for name lookups without a city ("Austin, TX", "Manchester, UK").

## `maxPlacesPerQuery` (type: `integer`):

How many businesses each search query may add.

## `onlyWithEmail` (type: `boolean`):

Skip businesses where no e-mail could be found (they are free either way).

## `maxBusinesses` (type: `integer`):

Upper bound on businesses processed in one run.

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

Check syntax and the domain's mail server for every address; undeliverable addresses are dropped.

## `smtpVerification` (type: `boolean`):

Also ask the mail server whether the mailbox exists (and detect catch-all domains). Falls back to the mail-server check when SMTP is not reachable.

## `searchMining` (type: `boolean`):

Search for the business and read e-mails from result snippets and top result pages (directories, associations, local press) — where owner e-mails usually hide. Only e-mails clearly attributable to the business are kept.

## `maxSearchQueries` (type: `integer`):

Up to this many searches per business (domain search, name + city + email, name + owner).

## `searchResultPagesToFetch` (type: `integer`):

How many top result pages (one per site) are fetched and mined for e-mails.

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

Home page plus contact / about / team / imprint pages crawled per website.

## `includeGuessedEmails` (type: `boolean`):

When the owner's name is known but no owner address was found, add likely addresses on the business domain (first@, first.last@…). Only kept when the mailbox check confirms them.

## `countryCode` (type: `string`):

Two-letter country code for the business lookups (us, gb, de, …).

## `language` (type: `string`):

Two-letter language code for the business lookups.

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

How many businesses are processed at once.

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

Proxy used for the business listing lookups and searches. Apify datacenter proxy by default. Website crawls go direct and fall back to the proxy automatically when a site challenges the platform IP.

## `apifyMcpConnector` (type: `string`):

Optional. Connect an Apify MCP connector (Console → Settings → Integrations → MCP Connectors, server URL https://mcp.apify.com) and the discovery searches run as our published business finder under THAT account. Leave empty to run everything built in, on this run.

## Actor input object example

```json
{
  "businesses": [
    "Beyond Wow Plumbing & Drains, Austin TX",
    "reliantplumbing.com"
  ],
  "searchQueries": [
    "dentists"
  ],
  "location": "Austin, TX",
  "maxPlacesPerQuery": 50,
  "onlyWithEmail": false,
  "maxBusinesses": 500,
  "verifyEmails": true,
  "smtpVerification": true,
  "searchMining": true,
  "maxSearchQueries": 3,
  "searchResultPagesToFetch": 3,
  "maxPagesPerSite": 6,
  "includeGuessedEmails": false,
  "countryCode": "us",
  "language": "en",
  "maxConcurrency": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per business: primary and owner e-mail, owner name, phone, website, address, socials, status.

## `emails` (type: `string`):

Every e-mail with its type, source page, confidence and verification.

## `owners` (type: `string`):

Businesses where the owner or a named contact was identified.

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

Counts and verification stats.

# 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 = {
    "businesses": [
        "Beyond Wow Plumbing & Drains, Austin TX",
        "reliantplumbing.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("inovaflow/local-business-email-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 = {
    "businesses": [
        "Beyond Wow Plumbing & Drains, Austin TX",
        "reliantplumbing.com",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("inovaflow/local-business-email-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 '{
  "businesses": [
    "Beyond Wow Plumbing & Drains, Austin TX",
    "reliantplumbing.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call inovaflow/local-business-email-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,inovaflow/local-business-email-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/JFH7cQLe6cd3XcdPd/builds/Ove9z52Ztcz0rRQWw/openapi.json
