# Website Business Contact Extractor (`jj_toolworks/website-business-contact-extractor`) Actor

Extract publicly listed shared business contacts from supplied websites, with original record IDs, source evidence and clear per-site coverage. HTTP-only, up to five pages per site.

- **URL**: https://apify.com/jj_toolworks/website-business-contact-extractor.md
- **Developed by:** [JJ Toolworks](https://apify.com/jj_toolworks) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$8.00 / 1,000 completed results

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

## Website Business Contact Extractor

Turn a known list of organization websites into public business contact assessments with exact source evidence. Every input retains its `recordId`, including inputs with no contact, failures and duplicates.

### Use it for

Refresh shared business channels in a CRM, review supplier contact details, or attach published contact evidence to a business directory. Select general, trades, manufacturing, property management, hospitality or B2B software link priorities. The preset changes which contact-oriented pages the crawler selects first; it does not guess people or purchase enrichment.

### Start

```json
{
  "websites": [{"url": "https://www.w3.org/contact/", "recordId": "demo-w3c"}],
  "preset": "general",
  "maxPagesPerSite": 3
}
```

A URL string is also accepted. `websites` contains 1–100 entries. Record IDs are returned as strings, capped at 160 characters. An empty input is rejected before fetching.

### Output

Filter the dataset to `recordType = assessment`. Each assessment includes `recordId`, source/final URL, `status`, `complete`, `emails`, `phones`, convenient primary fields, contact-level source evidence, the pages checked, failures, omitted candidate count and timestamp. Filter `recordType = run_summary` for totals and a compact `CONTACTS` JSON file link. Apify's dataset export provides CSV/JSON formats.

An email contact includes a role label and exact evidence sources. Role mailboxes are extracted from visible text and mailto links. Explicit Organization/ContactPoint structured data can supply a source-declared organization contact. Person records are skipped. Phone links are normalized conservatively; their country and operating status are not verified. Explicit mobile/cell/personal/direct-line labels and marked Person records are excluded.

`association` is `branch` when structured data supplies a parent/branch relationship, `corporate` for source-declared Corporation contacts, otherwise `uncertain`. Conflicting source associations remain uncertain. No relationship is inferred from a location-looking URL.

### Completion and pricing

The configured event price is **$8 per 1,000 completed website assessments** ($0.008 each). The billable unit is one unique supplied website URL assessed within its selected maximum-page scope. `complete_no_contacts` is a billable completed assessment; it does not claim there is no contact elsewhere. `scopeExhaustive` and `contactCandidatesOmittedByPageScope` describe the selected crawl's coverage.

Blocked, invalid, unsupported, timed-out or incomplete assessments and contact-cap results do not create a success event. A duplicate normalized input retains its own assessment/record ID without a second charge. UTM/tracking parameters and fragments are removed for URL identity. Different start paths on one domain are separate assessments because they define different scopes.

### Limits

| Limit | Scope |
|---|---|
| Websites | 100 per run |
| Pages | 1–5 selected pages per website, including supplied URL |
| Host | Root may redirect between bare/www forms; subsequent selected pages stay on the final root host |
| HTML bytes | 2 MiB per page |
| Time | 60-second website budget, requests up to 20 seconds within that budget |
| Contacts | 150 distinct contacts per assessment; exceeding this marks it incomplete |
| Rendering | Static HTTP only |

There is no browser fallback, CAPTCHA handling, authenticated access, deliverability check, personal contact database or complete-site guarantee. An access challenge or failed selected contact page produces an explicit non-billable result. A failed page can coexist with useful contacts already found; that assessment is still incomplete and unbilled.

### Industry examples

Use `trades` for quote/estimating/service link priority, `manufacturing` for wholesale/dealer/distributor pages, `property_management` for leasing/management/location pages, and `hospitality` for reservations/events/groups. Preserve your own supplier, contractor or property-manager IDs as `recordId` for joining the result back to your workflow.

### Technical references

Organization contact semantics: https://schema.org/Organization and https://schema.org/ContactPoint. Competitive research and unmeasured unit-cost assumptions are documented in the source bundle's `MARKET.md`. No comparative accuracy or revenue claim is made.

### Price and run controls

The launch price is **$8 per 1,000 completed units** ($0.008 per event), as defined above. Check the current Pricing tab before running. Status and duplicate rows do not add this custom event. Set a maximum charge appropriate for your batch; a run stops when its event budget is exhausted. `RUN-SUMMARY` records actual accepted events and execution totals.

Automatic replay of an interrupted run is disabled to prevent duplicate charges. Keep the available output, then start a new run for a new execution. A later run is a new billable execution. Completed dataset rows and individually saved files remain available when a budget stops a run. Combined exports, manifests, and snapshots assembled at the end may be absent after a budget stop or interruption; use a sufficient run budget when you need those aggregate files. The initial release uses documented input limits and public source access; external source changes can require maintenance.

# Actor input Schema

## `websites` (type: `array`):

1–100 public website URLs or objects such as {"url":"https://example.org","recordId":"vendor-17"}. Supply known organization websites, not personal profiles.

## `preset` (type: `string`):

Changes the contact-oriented links visited first; stays within the same cost and page limits.

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

Root plus up to four same-host contact-related pages. Completion is within this selected scope; known omitted candidates are reported.

## Actor input object example

```json
{
  "websites": [
    {
      "url": "https://www.w3.org/contact/",
      "recordId": "demo-w3c"
    }
  ],
  "preset": "general",
  "maxPagesPerSite": 1
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "websites": [
        {
            "url": "https://www.w3.org/contact/",
            "recordId": "demo-w3c"
        }
    ],
    "preset": "general",
    "maxPagesPerSite": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("jj_toolworks/website-business-contact-extractor").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 = {
    "websites": [{
            "url": "https://www.w3.org/contact/",
            "recordId": "demo-w3c",
        }],
    "preset": "general",
    "maxPagesPerSite": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("jj_toolworks/website-business-contact-extractor").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 '{
  "websites": [
    {
      "url": "https://www.w3.org/contact/",
      "recordId": "demo-w3c"
    }
  ],
  "preset": "general",
  "maxPagesPerSite": 1
}' |
apify call jj_toolworks/website-business-contact-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jj_toolworks/website-business-contact-extractor"
        }
    }
}
```

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/KIAlRF7gyjJStWrkE/builds/Qc5JfV67q0GuCVKOU/openapi.json
