# Coder~devil (`lamplit_weever/coder-devil`) Actor

- **URL**: https://apify.com/lamplit\_weever/coder-devil.md
- **Developed by:** [coder Devil](https://apify.com/lamplit_weever) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## Byndex Lead Finder

An Apify Actor for the discovery stage of Byndex: find local businesses for one category, city, and country, then recover public email routes from their official websites with source evidence.

### Version 0.3.3 goal

The pilot target is **at least 31 clean public emails from 50 accepted businesses**. This is a measured target, not a guaranteed yield: some real businesses publish no email at all.

Version 0.3.3 (V3.2.1) does not invent or permute an address. It can evaluate up to 70 accepted businesses for a 50-lead run, crawl their official websites, retry unreachable sites with bounded hostname/protocol variants, and use Chromium only for sites that remain unreachable. `clean_public_email_count` measures addresses that passed strict syntax/domain rules and appeared in a public source. `outreach_eligible_email_count` is the stricter subset after domain, page-purpose, role-usefulness, and branch ranking. Neither status proves that a mailbox currently exists or can receive mail.

### Workflow

1. Call the configured discovery Actor (default: `compass/crawler-google-places`).
2. Normalize and deduplicate business identity, address, official website, map URL, rating, reviews, and phone.
3. Reject out-of-city records and records without an official website by default.
4. Build a candidate pool larger than the final output (default: 1.4×, up to 70 candidates for 50 leads).
5. Crawl the starting website page, homepage, `/contact`, and `/contact-us` for every pool candidate.
6. Retry fully unreachable websites with bounded HTTPS/HTTP and `www`/non-`www` variants.
7. Use a two-page Playwright fallback only when both normal HTTP phases fail.
8. Follow the strongest same-site contact, location, office, support, team, staff, about, privacy, legal, and company links up to the page limit.
9. Recover emails from explicit public evidence channels in this priority order:
   - `mailto:` links
   - JSON-LD `email` properties
   - safe email data attributes
   - Cloudflare-protected email attributes
   - visibly obfuscated text such as `name [at] domain [dot] com`
   - ordinary visible page text
10. Rank automation-eligible addresses first, then compare domain quality, target-branch/location evidence, page purpose, extraction source, and page relevance.
11. Select the final leads from the fully evaluated pool: official-domain eligible email, free-provider eligible email, review email, phone-only, then website-only. Original order is preserved inside each tier.
12. Publish exactly one eligible primary address in `public_emails`; isolate alternates, possible other-location routes, and review-only routes in separate fields.
13. Store evaluated non-selected records in `RESERVE_LEADS`, then publish candidate evidence, review status, quality flags, and a run-level yield report.

### V3.2.1 quality controls

- Preserves DOM boundaries before reading visible text, preventing labels and phone numbers from being joined to emails.
- Never scans arbitrary JavaScript, styles, SVG, templates, or raw HTML for addresses.
- Requires an ICANN-recognized public suffix and rejects asset extensions, monitoring domains, placeholders, no-reply routes, legal-only routes, and malformed domain suffixes.
- Includes regression coverage for the exact V2 failures such as `.comall`, `.comsitemapbottom`, phone-prefixed local parts, Wix/Sentry strings, and image filenames.
- Keeps the correct email source type and source URL for the selected primary address.
- Evaluates a configurable surplus pool before final selection, so a phone-only business discovered early cannot displace a stronger email lead discovered later.
- Treats a city in a source URL as branch evidence only on contact/location pages or the exact official starting path. Unrelated city articles do not receive target-branch status.
- Records `crawl_failure_reason`, `crawl_http_status`, `crawl_retry_count`, and `crawl_recovery_method` on every lead.
- Moves secondary person/location mailboxes from different office pages into `other_location_emails` for review.
- Recognizes a narrowly defined official-site brand alias only when an explicit evidence channel publishes it on the official site and both domain stems share a strong prefix. It remains review-only as `OFFICIAL_SITE_BRAND_ALIAS_REVIEW`.
- Marks person/location mailboxes found only on privacy, legal, terms, HIPAA, or privacy-notice pages as `REVIEW_EMAIL_PAGE_PURPOSE`.
- Prefers non-legal evidence when the same address also appears on a normal contact, location, or home page.
- Adds explicit confidence labels: `PUBLIC_SOURCE_HIGH_CONFIDENCE`, `PUBLIC_SOURCE_MEDIUM_CONFIDENCE`, `REVIEW_REQUIRED`, and `NOT_AVAILABLE`.
- Sends automated-response routes such as `responses@...` and corporate-support routes such as `customerservice@...` to review instead of approving them for outreach.
- Keeps domain mismatches, low-usefulness routes, alternates, and possible other-location addresses out of the automation-safe `public_emails` field.
- Deduplicates US phone formats by canonical digits.
- Uses website phones only to confirm the discovery phone. It does not append unrelated branch numbers. If discovery has no phone, it accepts one explicit official-site `tel:` route.
- Keeps every n8n-facing scalar field present even when empty.

### Input example

```json
{
  "category": "dentists",
  "city": "Phoenix",
  "country": "United States",
  "maxLeads": 50,
  "prioritizeOutreachEligible": true,
  "candidatePoolMultiplier": 1.4,
  "minimumOutreachEligible": 31,
  "crawlOfficialWebsites": true,
  "usePlaywrightFallback": true,
  "maxPagesPerWebsite": 8,
  "strictCityMatch": true,
  "requireWebsite": true
}
```

`maxPagesPerWebsite` defaults to 8 and can be set from 1 to 12. With the defaults, a 50-lead run evaluates up to 70 accepted websites before selecting the final 50. This can increase discovery and crawl cost by roughly 40%, so first measure it on one 50-lead pilot. `minimumOutreachEligible` is a reporting target; it never weakens a review rule or guarantees the result.

### Important output fields

The dataset keeps the existing `leadfinal` identifiers and business fields. V3.2.1 adds or stabilizes:

- `email`, `public_emails`, `alternate_public_emails`, `other_location_emails`, `review_emails`
- `email_candidate_count`, `email_candidate_evidence`
- `email_source_type`, `email_source_url`
- `email_domain_status`, `email_verification_status`, `email_role_type`
- `email_usefulness_status`, `email_outreach_eligibility`
- `email_location_status`, `email_location_score`
- `email_page_purpose`, `email_confidence_status`
- `contact_review_status`
- `candidate_pool_order`, `candidate_pool_size`, `reserve_count`, `selected_beyond_initial_limit`
- `selection_rank`, `selection_status`, `selection_reason`
- `phone`, `public_phones`, `phone_evidence_status`
- `website_crawl_status`, `pages_crawled_count`, `crawl_failure_reason`, `crawl_http_status`, `crawl_retry_count`, `crawl_recovery_method`
- `discovery_quality_status`
- `quality_flags`, `quality_flag_count`, `quality_flags_text`
- `discovery_source`, `website_evidence`

Recommended n8n gate for the normal clean-email path:

```text
discovery_quality_status = APPROVED
AND contact_review_status = EMAIL_FOUND_CLEAN
AND email_outreach_eligibility = ELIGIBLE
AND email_confidence_status IN (PUBLIC_SOURCE_HIGH_CONFIDENCE, PUBLIC_SOURCE_MEDIUM_CONFIDENCE)
AND email is not empty
AND email_source_url is not empty
```

Use `public_emails[0]` or `email` only after this complete gate passes. A non-empty `email` can intentionally remain visible on a review record; that is evidence for a human, not permission to send.

For the strictest branded-email subset, also require:

```text
email_domain_status = WEBSITE_DOMAIN_MATCH_UNVERIFIED
AND email_confidence_status = PUBLIC_SOURCE_HIGH_CONFIDENCE
```

Send `REVIEW_EMAIL_DOMAIN`, `REVIEW_EMAIL_DOMAIN_ALIAS`, `REVIEW_EMAIL_PAGE_PURPOSE`, `REVIEW_EMAIL_USEFULNESS`, and `REVIEW_EMAIL_LOCATION` records to manual review. Never send `NO_PUBLIC_EMAIL_FOUND` records into an email campaign. Do not automatically merge `alternate_public_emails`, `other_location_emails`, or `review_emails` into an outreach list.

### Run summary

`RUN_SUMMARY` separately reports the evaluated pool, selected and reserve counts, public emails found, clean public-source emails, outreach-eligible emails, confidence levels, fully automation-ready emails, role/domain/page/branch review counts, missing emails, and whether the configured target was achieved.

`REJECTED_LEADS` stores hard-rejected records separately.

`RESERVE_LEADS` stores fully evaluated candidates that did not enter the final `maxLeads` dataset. They are evidence-backed backups, not automatic additions to an outreach campaign.

### Intentional boundaries

- No guessed addresses or permutations.
- No SMTP mailbox probing or deliverability claim.
- No Hunter, ZeroBounce, LinkedIn automation, subscription forms, support chat, or outreach.
- The source Actor is a replaceable adapter. Follow source terms, website terms, privacy law, suppression requirements, and outreach law for every market.

### Deploy and pilot

1. Authenticate the Apify CLI with the intended account.
2. From this project folder, run `npm test`.
3. Run `npx apify push --open`.
4. Start a new 50-business pilot with the input example.
5. Confirm both `clean_public_email_count` and `outreach_eligible_email_count` in `RUN_SUMMARY`.
6. Inspect every review bucket before connecting the strict n8n gate.

For lakhs of leads, split work by category and geographic job in n8n. Keep discovery, deduplication, contact recovery, later risk checks, and outreach eligibility as separate stages.

# Actor input Schema

## `category` (type: `string`):

Examples: dentists, accounting firms, solar installers.

## `city` (type: `string`):

City to search for businesses.

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

Country containing the target city.

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

Use 25–50 for the first quality test. Large runs should be split by city or geographic grid in the orchestrator.

## `prioritizeOutreachEligible` (type: `boolean`):

Evaluates a larger business pool, then selects source-backed email leads before phone-only and website-only records. Disable this to preserve discovery order.

## `candidatePoolMultiplier` (type: `number`):

When prioritization and website crawling are enabled, evaluates this multiple of maxLeads before selecting the final dataset. 1.4 means up to 70 candidates for 50 outputs.

## `minimumOutreachEligible` (type: `integer`):

Run-reporting target only; it never relaxes safety rules or guarantees yield. For a 50-lead pilot, use 31.

## `crawlOfficialWebsites` (type: `boolean`):

Visits the official website and relevant internal contact, location, team, about, support, and legal pages. It never generates guessed addresses.

## `usePlaywrightFallback` (type: `boolean`):

After bounded HTTP retries fail, tries at most two pages in Chromium. Disable this to avoid browser fallback cost.

## `maxPagesPerWebsite` (type: `integer`):

Starts with the website, homepage, /contact, and /contact-us, then follows the strongest relevant internal links up to this limit.

## `strictCityMatch` (type: `boolean`):

Keeps a result only when its public address contains the requested city.

## `requireWebsite` (type: `boolean`):

Rejects listings without an official website from the main lead dataset.

## `sourceActorId` (type: `string`):

The default is the reviewed Google Places discovery adapter. Change it only after reviewing the replacement Actor's input and output schema.

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

Optional Apify proxy settings. This applies only to official website pages crawled by this Actor.

## Actor input object example

```json
{
  "category": "dentists",
  "city": "Phoenix",
  "country": "United States",
  "maxLeads": 50,
  "prioritizeOutreachEligible": true,
  "candidatePoolMultiplier": 1.4,
  "minimumOutreachEligible": 31,
  "crawlOfficialWebsites": true,
  "usePlaywrightFallback": true,
  "maxPagesPerWebsite": 8,
  "strictCityMatch": true,
  "requireWebsite": true,
  "sourceActorId": "compass/crawler-google-places"
}
```

# Actor output Schema

## `leads` (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 = {
    "category": "dentists",
    "city": "Phoenix",
    "country": "United States"
};

// Run the Actor and wait for it to finish
const run = await client.actor("lamplit_weever/coder-devil").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 = {
    "category": "dentists",
    "city": "Phoenix",
    "country": "United States",
}

# Run the Actor and wait for it to finish
run = client.actor("lamplit_weever/coder-devil").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 '{
  "category": "dentists",
  "city": "Phoenix",
  "country": "United States"
}' |
apify call lamplit_weever/coder-devil --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lamplit_weever/coder-devil"
        }
    }
}

```

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/gV24od8UZSXwhVAu1/builds/LeoAI49rj1VYZQ5W6/openapi.json
