# Website Email Scraper & Contact Finder: Phones & Socials (`cygnix_labs/outreach-contact-finder`) Actor

Website email scraper, contact finder and contact details scraper for outreach and lead enrichment. Paste domains or URLs; get emails, phones (incl. WhatsApp), contact/impressum pages and LinkedIn, X, Facebook, Instagram, YouTube, TikTok per domain. 5 domains free, then $0.004/domain with contacts.

- **URL**: https://apify.com/cygnix_labs/outreach-contact-finder.md
- **Developed by:** [Umair Saleem Mohammad Saleem](https://apify.com/cygnix_labs) (community)
- **Categories:** Lead generation, SEO tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 domain with contacts

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 Email Scraper & Contact Finder: Phones & Socials

**Answer first:** this actor is a **website email scraper and contact details scraper (an outreach contact finder) for link-building outreach and lead enrichment**. Give it a list of **website URLs or domains**. For each domain it reads the homepage and the most likely **contact, impressum, about, team, support and press pages**, then returns **emails, phone numbers (including WhatsApp click-to-chat numbers), the contact page URL and the company's LinkedIn, X (Twitter), Facebook, Instagram, YouTube and TikTok profiles**, one row per domain. Junk is filtered out (example@ addresses, `image@2x.png`, Sentry/Wix tracking addresses, noreply). **The first 5 domains of every run are free, then $0.004 per domain where contacts were found ($4 per 1,000).** Domains with nothing found, dead sites and robots-blocked sites are never billed.

| Quick facts | |
|---|---|
| Best for | Extracting emails from a list of websites, link-building outreach lists, guest-post and PR prospecting, lead enrichment, CRM clean-up, finding a company's social profiles |
| Input | A list of domains or URLs (`plausible.io`, `https://basecamp.com`) |
| Output | One row per domain: `primaryEmail`, `emails`, `phones`, `contactPageUrl`, `linkedin`, `x`, `facebook`, `instagram`, `youtube`, `tiktok`, `aboutPages`, plus `emailDetails` (where each email was found) and `phoneDetails` (with a `normalized` digits form) |
| Price | First 5 domains free every run, then **$0.004 per domain with contacts**. Same price for 1 or 10 pages per domain. No start fee |
| Needs | No API keys, no proxies, no login. Public pages only |
| Not included | Email verification (SMTP), people search by job title, JavaScript-rendered pages, Google Maps |

**Try it now:** the input is prefilled with 3 domains, so the first run is free.

### Sample output (real run, 19 Oct 2026, 12 domains)

Unedited output of build 0.1.5, run `4lIeBJ6uvZbajg9M8`: `{"urls": ["plausible.io", "basecamp.com", "ahrefs.com", "usefathom.com", "ghost.org", "buffer.com", "joesbakery.com", "franklinbbq.com", "tartinebakery.com", "vapiano.de", "expired.badssl.com", "nonexistent-cygnix-xyz.com"], "maxPagesPerDomain": 5}`. 35 pages fetched in 3.9 seconds of run time. 10 domains had contacts (5 free, 5 billed: **$0.02**), the expired-certificate test site was read but had no contacts (free), and the made-up domain came back `unreachable` (free). Platform cost of the whole run: $0.00029.

**Download the full sample (all 12 rows with every field, public, no login):** [JSON](https://api.apify.com/v2/datasets/I4OFjsny58IGVyYpn/items?format=json\&clean=1) · [CSV](https://api.apify.com/v2/datasets/I4OFjsny58IGVyYpn/items?format=csv\&clean=1) · [Excel](https://api.apify.com/v2/datasets/I4OFjsny58IGVyYpn/items?format=xlsx\&clean=1)

| Domain | Best email | Phones | Contact page | Socials found |
|---|---|---|---|---|
| plausible.io | hello@plausible.io | - | plausible.io/contact (+ imprint) | LinkedIn, X |
| usefathom.com | support@usefathom.com | - | usefathom.com/about/contact | LinkedIn, X, YouTube |
| ghost.org | support@ghost.org | - | ghost.org/contact/ (+ help) | - |
| basecamp.com | jason@basecamp.com | - | basecamp.com/support | - |
| ahrefs.com | support@ahrefs.com (+ pr@ahrefs.com) | - | - (about + team pages read) | LinkedIn, X, Facebook, Instagram, YouTube |
| buffer.com | press@buffer.com | - | buffer.com/press | LinkedIn, X, Facebook, Instagram |
| joesbakery.com | contact@joesbakery.com (+ a Gmail address) | +15124720017, 7346651852 | joesbakery.com/contact-us/ | X, Facebook, Instagram |
| franklinbbq.com | hello@franklinbbq.com | 512-653-1187 | franklinbbq.com/contact | Facebook, Instagram |
| tartinebakery.com | info@tartinebakery.com (+ press@) | - | tartinebakery.com/press | Facebook, Instagram |
| vapiano.de | info@vapiano.de | 05121 - 9127 - 0 | vapiano.de/kontakt (+ impressum) | Facebook, Instagram, TikTok |
| expired.badssl.com | - | - | - | - (status `ok (no contacts found)`, `tlsWarning: invalid TLS certificate (CERT_HAS_EXPIRED); read anyway`) |
| nonexistent-cygnix-xyz.com | - | - | - | - (status `unreachable`, `error: ENOTFOUND`) |

Ahrefs and Tartine hide their addresses behind Cloudflare email protection; the actor decodes those. Buffer and Basecamp have no `/contact` page: the actor now also reads support and press pages, which is where `press@buffer.com` was found (build 0.1.3 returned no email for Buffer).

One row from the dataset (trimmed):

```json
{
  "domain": "joesbakery.com",
  "status": "ok",
  "siteName": "Joe's Bakery & Coffee Shop - Mexican Food | Austin",
  "primaryEmail": "contact@joesbakery.com",
  "emails": ["contact@joesbakery.com", "basilicofood123@gmail.com"],
  "emailDetails": [
    { "email": "contact@joesbakery.com", "source": "mailto link", "page": "https://joesbakery.com/", "sameDomain": true },
    { "email": "basilicofood123@gmail.com", "source": "mailto link", "page": "https://joesbakery.com/", "sameDomain": false }
  ],
  "phones": ["+15124720017", "7346651852"],
  "phoneDetails": [
    { "phone": "+15124720017", "normalized": "+15124720017", "source": "schema.org", "page": "https://joesbakery.com/" },
    { "phone": "7346651852", "normalized": "7346651852", "source": "tel link", "page": "https://joesbakery.com/" }
  ],
  "contactPageUrl": "https://joesbakery.com/contact-us/",
  "aboutPages": ["https://joesbakery.com/about-us/"],
  "x": "https://x.com/joesbakeryatx",
  "facebook": "https://www.facebook.com/joesbakeryandcoffeeshop",
  "instagram": "https://www.instagram.com/joesbakeryeatx",
  "pagesCrawled": 3,
  "tlsWarning": null,
  "charged": false
}
```

### What you get per domain

| Field | What it is |
|---|---|
| `primaryEmail` | The best outreach address: on the site's own domain first, generic inboxes (hello@, info@, contact@, press@, partners@, kontakt@) before privacy@ / legal@ / dpo@ / DSA-authority / webmaster@ / jobs@ addresses |
| `emails`, `emailDetails` | Every unique email, lower-cased and de-duplicated, with the source (`mailto link`, `page text`, `schema.org`, `cloudflare-protected`), the page it was on and `sameDomain` (true for the domain you entered and the domain it redirects to, e.g. `netcup.de` -> `netcup.com`) |
| `phones`, `phoneDetails` | Numbers from `tel:` links, WhatsApp click-to-chat links (`wa.me`, `api.whatsapp.com`), schema.org `telephone` and text right after a "Phone / Tel / Telefon / Call us" label. The same number with and without country code is merged, including German-style `+49 (0)9831 ...` vs `0049 9831 ...`. `phoneDetails[].normalized` is the digits-only form (with `+` when the site gave a country code) for CRM import |
| `contactPageUrl`, `contactPages` | Contact, impressum / imprint / legal-notice, support / help and press pages actually fetched (English, German, French, Spanish, Italian, Portuguese paths). `contactPageUrl` is the real contact page when one exists, otherwise the impressum, support or press page |
| `aboutPages` | About, our story and team pages fetched |
| `linkedin`, `x`, `facebook`, `instagram`, `youtube`, `tiktok` | The profile that looks like the company (handle matches the domain or site name) |
| `socialProfiles` | All profile links found per network, e.g. founders' LinkedIn pages from a team page |
| `status` | `ok`, `ok (no contacts found)`, `unreachable`, `HTTP 404`, `blocked by robots.txt`, `error` (with `error` for the reason, e.g. `ENOTFOUND`). Every domain you enter gets a row |
| `tlsWarning`, `fallbackUrlUsed` | Set when the site's TLS certificate is expired / self-signed / for another host and the page was read anyway, or when the www / non-www twin or `http://` had to be used |
| `charged` | Whether this row was billed |

A `SUMMARY` record in the key-value store has run totals (domains, with contacts, failed, billed, free).

#### What gets filtered out

Placeholder and junk emails never reach your list: `example@`, `you@yourdomain.com`, `name@domain.com`, `john.doe@company.com`, image file names that look like emails (`logo@2x.png`), Sentry and Wix tracking addresses (`...@sentry.io`, `...@sentry-next.wixpress.com`), long hex hashes, `noreply@` / `donotreply@`, and stray `u003e` / `%20` prefixes from scripts (real addresses that start with digits, like `20north@...`, are kept intact). Share buttons (`twitter.com/intent`, `facebook.com/sharer`), Instagram post URLs and TikTok video URLs are not counted as profiles. Phone placeholders like `0123456789` and US fictional 555-01xx numbers are dropped.

### Input

```json
{
  "urls": ["plausible.io", "https://basecamp.com", "ahrefs.com"],
  "maxPagesPerDomain": 5,
  "sameDomainEmailsOnly": false,
  "respectRobotsTxt": true,
  "maxConcurrency": 10
}
```

| Field | Default | What it does |
|---|---|---|
| `urls` (required) | | Domains or URLs, one per line. Duplicates and www / non-www twins are merged. `startUrls` (`[{"url": ...}]`) is accepted too |
| `maxPagesPerDomain` | 5 | Homepage + up to N-1 of the most likely contact / impressum / about / team pages (max 10). Price is per domain, not per page |
| `sameDomainEmailsOnly` | false | Keep only emails on the site's own domain |
| `respectRobotsTxt` | true | Skips pages robots.txt disallows for `CygnixContactFinder` |
| `maxConcurrency` | 10 | Domains in parallel. Pages within one domain are fetched one at a time |
| `requestTimeoutSecs` | 20 | Per page |

### What a run costs

You pay only for domains where at least one email, phone or social profile was found. **The first 5 such domains in every run are free.** No start fee.

| Domains with contacts | You pay |
|---|---|
| 5 | **$0** (free in every run) |
| 100 | $0.38 |
| 500 | $1.98 |
| 1,000 | $3.98 |
| 10,000 | $39.98 |

Set **Maximum cost per run** in the run options and the actor stops cleanly when it is reached. It runs on 512 MB with plain HTTP (no browser, no proxy), so it is fast: the 10-domain sample above took under 8 seconds.

### How it compares (live Apify Store prices, verified 19 Oct 2026, spot-checked 21 Oct 2026)

List prices on the Apify Free plan, read from the Apify Store API on 19 October 2026 (18:20 Riyadh time). Some actors charge less on higher Apify plans. "1,000 domains" assumes one run and about 5 pages per domain.

| Actor | Price on the Free plan | Cost for 1,000 domains | Monthly users | Billed when nothing is found? |
|---|---|---|---|---|
| **cygnix_labs/outreach-contact-finder** (this) | **$0.004 per domain with contacts, first 5 free every run, no start fee** | **$3.98** | new | **No** |
| vdrmota/contact-info-scraper | $0.002 per page + $0.001 start per GB; paid lead / social add-ons | ~$10 (5 pages); ~$2 homepage only | 2,977 | Yes (per page) |
| automation-lab/website-contact-finder | $0.035 per run + $0.001 per website returned; email verification $0.002 | ~$1.04 | 94 | Yes |
| solidscrape/contact-details-scraper | $0.00125 per result + tiny start fee | ~$1.25 (1 row per site) | 56 | Yes |
| dami_studio/contact-details-scraper | $0.0015 per site with contacts | ~$1.50 | 3 | No |
| datagleaner/website-contact-details-scraper | $0.002 per website with an email | up to $2 | 17 | No |
| siftwright/contact-details-extractor | $0.002 per website scanned + tiny start fee | ~$2 | 5 | Yes (failed loads free) |
| poidata/contact-details-scraper | $0.002 per result + tiny start fee | ~$2 (1 row per site) | 54 | Yes |
| jfaro19/website-contact-finder | $0.003 per website with an email or phone + tiny start fee | up to $3 | 13 | No |
| khadinakbar/contact-details-scraper | $0.003 per domain + tiny start fee | ~$3 | 27 | Yes |
| emastra/website-contact-scraper | $0.004 per domain + tiny start fee | ~$4 | 58 | Yes |
| logiover/website-contact-scraper | $0.005 per result | ~$5 | 37 | Yes |
| thenetaji/website-email-scraper | $0.005 per result (Free plan) | ~$5 | 78 | Yes |
| jurassic_jove/website-email-extractor | $0.006 per result + tiny start fee | ~$6 | 75 | Yes |
| compass/contact-details-scraper-standby | $0.006 per website | ~$6 | 1 | Yes |
| delicious_zebu/contact-info-scraper | $0.01 per result | ~$10 | 99 | Yes |
| caprolok/website-email-phone-finder | $0.02 per result | ~$20 | 81 | Yes |

**Honest take.** vdrmota's Contact Details Scraper is the proven leader (4.7 stars, 92 reviews) and does more: deep crawls, browser rendering, residential proxies and paid lead enrichment. It costs about $0.01 per domain at 5 pages, or about $0.002 if you only scrape the homepage. On big single runs several actors are cheaper per domain than us (automation-lab, solidscrape, dami_studio, datagleaner, siftwright, poidata, jfaro19, khadinakbar). Pick this actor when you want **small and medium runs free or close to free (5 free domains in every run, nothing billed for empty or dead domains), homepage + contact + impressum + about + team + support + press pages for one flat price, a ranked best outreach email and the source page of every email and phone**. code_crafter/leads-finder (2,012 users) is a different tool: it searches a B2B people database by job title rather than reading websites.

### For AI agents / MCP

**When an agent should call this actor:** the user has a list of websites or domains and asks for their contact emails, phone numbers, contact page or social media profiles, wants to build an outreach or link-building list, or wants to enrich leads or a CRM export with emails and LinkedIn pages.

Connect the Apify MCP server with only this actor enabled (works in Claude, ChatGPT, Cursor, VS Code, Codex and any MCP client):

```
https://mcp.apify.com?tools=cygnix_labs/outreach-contact-finder
```

Or search for it with the default server: `search-actors` keywords such as `contact details scraper`, `email finder from website`, `outreach contact finder`, `social links extractor`.

Example `call-actor` input:

```json
{
  "urls": ["plausible.io", "ghost.org", "franklinbbq.com"],
  "maxPagesPerDomain": 5
}
```

**What to read from the result:** each dataset row is one domain: `primaryEmail` (best outreach address), `emails`, `phones`, `contactPageUrl`, `linkedin`, `x`, `facebook`, `instagram`, `youtube`, `tiktok` and `status`. `emailDetails[].page` tells you where each address was published.

**Cost control for agents:** 5 domains are free in every run, then $0.004 per domain with contacts. Pass `maxTotalChargeUsd` in `callOptions` to hard-cap spend. This actor is pay-per-event, so it also works with Apify agentic payments (no Apify account needed for the agent).

Example prompt: *"Find the contact email, contact page and LinkedIn for these 40 blogs so I can pitch a guest post."*

### FAQ

**Where does it look?** The page you give (or the homepage), then the best-matching links on that page: contact, impressum / imprint, about, team, support / help and press. Short paths win over blog posts that only mention "contact" in the slug. If no contact link exists it tries `/contact` and `/contact-us` (Shopify stores: `/pages/contact`; `.de` / `.at` / `.ch` sites: `/kontakt`, plus `/impressum` when no imprint link is found). Privacy, cookie, terms and careers pages are skipped even when they sit under `/kontakt/`. It stays on the same domain and its subdomains.

**Does it verify emails?** No SMTP or mailbox checks. Every email was published on the site itself; `emailDetails` shows the exact page and how it was found (mailto link, page text, schema.org, Cloudflare-protected). Run a verifier before cold email at scale.

**Does it handle obfuscated emails?** Cloudflare email protection is decoded, and simple `name [at] domain [dot] com` text is recognised. Emails drawn as images or loaded by JavaScript are not.

**Does it render JavaScript?** No. It reads the HTML the server sends, which keeps it fast and cheap. Most business sites put contact details in server HTML; single-page apps that load everything with JavaScript may return fewer results.

**What about sites with an expired or self-signed certificate?** Small-business sites often have one. The actor reads the public page anyway (read-only, robots.txt still honoured) and flags the row with `tlsWarning`. If the domain does not answer, it also tries the www / non-www twin and plain `http://`, and says which one worked in `fallbackUrlUsed`.

**Does it find WhatsApp numbers?** Yes, when the site links to `wa.me/<number>` or `api.whatsapp.com/send?phone=<number>`; they appear in `phones` with source `whatsapp link`.

**Facebook pages without a username?** Links like `facebook.com/profile.php?id=1000...` keep their `id`, so the link still opens the page.

**Why was a domain not billed?** It had no email, phone or social profile on the pages checked, was unreachable, returned an error, or robots.txt blocked the homepage. You also get 5 free domains in every run.

**Is it legal?** It only reads public pages, sends one request at a time per domain, identifies itself (`CygnixContactFinder`) and respects robots.txt by default. Emails can be personal data under GDPR and similar laws; you are responsible for how you use them (legitimate interest, opt-out, CAN-SPAM).

**Can it find people by job title or company LinkedIn employees?** No, it reads what the website publishes. For people search use a B2B leads database actor.

**Does it work on Shopify stores?** Yes. Shopify themes often hide the contact link in a JavaScript menu, so the actor also tries `/pages/contact` on Shopify sites (0.1.7: deathwishcoffee.com went from 0 to 1 email this way).

**Does it work as an impressum scraper for German sites?** Yes. Impressum / imprint pages are read for every domain, and on `.de`, `.at` and `.ch` sites `/impressum` and `/kontakt` are tried even when the homepage does not link them. Company email and phone usually sit there.

**A mailto link lists several addresses?** `mailto:a@site.com,b@site.com` gives both addresses (0.1.7).

**Can I feed it Google Maps results?** Yes: export the `website` column from a Google Maps scraper and paste it into `urls`.

### Integrations

Run it through the Apify API, schedule it, or send results to Google Sheets, HubSpot, Make, Zapier, n8n, Clay or a webhook. Export as CSV or Excel for any outreach tool.

### Changelog

- **0.1.7** (2026-10-21): Fixes from real-site tests: emails on the domain you entered were marked `sameDomain: false` (and dropped by `sameDomainEmailsOnly`) when the site redirects to another brand domain (netcup.de -> netcup.com, fathom.video -> fathom.ai); privacy-policy pages under `/kontakt/` were picked as the contact page; `+49 (0)...` and `0049...` copies of one number were not merged; `mailto:` links with several addresses were dropped; tracking-parameter URLs were crawled as contact pages; an unexpected error dropped the domain from the output (now an unbilled `error` row). New: Shopify `/pages/contact` and DACH `/kontakt` + `/impressum` guesses; DSA-authority, DPO and webmaster@ addresses rank below generic inboxes. No price change.
- **0.1.6** (2026-10-19): README: new real sample (run 4lIeBJ6uvZbajg9M8, build 0.1.5), comparison table re-verified 19 Oct 2026 with 13 rival actors, new FAQs. No price change.
- **0.1.5** (2026-10-19): Sites with an expired, self-signed or wrong-host TLS certificate are read instead of reported `unreachable` (flagged in `tlsWarning`); robots.txt is honoured on them too.
- **0.1.4** (2026-10-19): Fixes: emails starting with `20` or `3e` were cut (`20north@` became `north@`); Facebook `profile.php?id=` links lost their id; blog posts with "contact" in the URL could take the slot of the real contact page; a contact link that redirected to the homepage was read twice. New: WhatsApp numbers, support / help / press pages, `phoneDetails[].normalized`, www / non-www and `http://` fallbacks (`fallbackUrlUsed`).
- **0.1.3** (2026-10-19): First public release (the sample above comes from build 0.1.2, same code; 0.1.3 adds this README). Domains or URLs in, emails + phones + contact/impressum/about/team pages + 6 social networks out. Cloudflare email decoding, junk filter, best-email ranking, phone de-duplication. $0.004 per domain with contacts, first 5 free every run. Rival prices verified 19 Oct 2026.

### More tools by Cygnix Labs

- [Website SEO Audit & Site Audit + AEO/GEO Checker](https://apify.com/cygnix_labs/site-seo-aeo-audit)
- [Internal Link Audit & Orphan Page Finder](https://apify.com/cygnix_labs/internal-link-audit)
- [AEO & GEO Audit + llms.txt Checker (URL list)](https://apify.com/cygnix_labs/aeo-readiness-checker)
- [Keyword Clustering + Content Briefs](https://apify.com/cygnix_labs/keyword-clusterer-brief)
- [Search Intent Classifier](https://apify.com/cygnix_labs/serp-intent-mapper)
- Free local SEO MCP server: [cygnix-seo-mcp](https://github.com/cygnixlabs-cmd/cygnix-seo-mcp) (`npx -y cygnix-seo-mcp`)

Questions or a feature request? Open an issue on this actor's Issues tab. We answer within 24 hours.

# Actor input Schema

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

One website per line: a domain (plausible.io) or a URL (https://basecamp.com). Duplicates and www/non-www twins are merged. The homepage plus the most likely contact, impressum, about, team, support and press pages are checked for each domain.

## `maxPagesPerDomain` (type: `integer`):

Homepage + up to N-1 contact/impressum/about/team/support/press pages. The price per domain is the same for 1 or 10 pages. 1 = homepage only (fastest).

## `sameDomainEmailsOnly` (type: `boolean`):

Drop emails on other domains (e.g. a Gmail address or an agency's address in the footer). Off by default; every email row says whether it is on the site's domain (emailDetails.sameDomain).

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

Domains processed in parallel. Pages inside one domain are fetched one at a time to stay polite.

## `respectRobotsTxt` (type: `boolean`):

Skip pages that robots.txt disallows for our user-agent (CygnixContactFinder). Domains whose homepage is disallowed are reported and never billed.

## `requestTimeoutSecs` (type: `integer`):

Per page. Slow or dead sites are reported as unreachable and never billed.

## Actor input object example

```json
{
  "urls": [
    "plausible.io",
    "basecamp.com",
    "ahrefs.com"
  ],
  "maxPagesPerDomain": 5,
  "sameDomainEmailsOnly": false,
  "maxConcurrency": 10,
  "respectRobotsTxt": true,
  "requestTimeoutSecs": 20
}
```

# 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 = {
    "urls": [
        "plausible.io",
        "basecamp.com",
        "ahrefs.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cygnix_labs/outreach-contact-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 = { "urls": [
        "plausible.io",
        "basecamp.com",
        "ahrefs.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("cygnix_labs/outreach-contact-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 '{
  "urls": [
    "plausible.io",
    "basecamp.com",
    "ahrefs.com"
  ]
}' |
apify call cygnix_labs/outreach-contact-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cygnix_labs/outreach-contact-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/pMY8nXfd13uTZJP7B/builds/ZlLrwBBx0ZakuaGSw/openapi.json
