Universal B2B Lead Magnet & Intent Enricher
Pricing
from $2.00 / 1,000 basic leads
Universal B2B Lead Magnet & Intent Enricher
Discovers B2B leads via a customer seed list or OpenStreetMap Overpass (Google Maps excluded on ToS grounds), crawls each site for contact info, checks email plausibility via DNS/MX, supports BYOK Hunter.io/PDL enrichment, and optionally scores buying intent via Claude Haiku 4.5.
Pricing
from $2.00 / 1,000 basic leads
Rating
0.0
(0)
Developer
Stefano Seggio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
15 hours ago
Last modified
Categories
Share
Universal B2B Lead Magnet & Intent Enricher — Apify Store Overview
Actor: stefano_seggio/actor-18-b2b-lead-magnet
Actor ID: 5QufcYxRkFNHM4h8K
Store URL: https://apify.com/stefano_seggio/actor-18-b2b-lead-magnet
Version: 1.1
Executive Summary & Business Use Case
Universal B2B Lead Magnet & Intent Enricher turns either a list of company names/domains you already have or a geographic bounding box into structured, contact-plausibility-checked B2B leads. It runs in one of two discovery modes: Mode A (seedList), where you supply the company names or website domains/URLs to enrich directly, and Mode B (osmOverpass), where it discovers candidate businesses from OpenStreetMap's ODbL-licensed Overpass API inside a bounding box you define ("south,west,north,east" in decimal degrees). Deliberately absent from either mode is Google Maps: the actor's own documentation is explicit that Google's Maps/Earth Additional Terms and Maps Platform Terms both prohibit building a "business listings database" from Maps content, so discovery runs against OpenStreetMap's Overpass API instead — a source whose license explicitly permits bulk extraction — or against a list the customer already owns. For every candidate business, the actor crawls the site's own server-delivered HTML, extracts any mailto: links or regex-matched email addresses, and checks the plausibility of the associated domain with a live DNS MX-record lookup — a real, deliberately-configured mail-receiving path, not a guessed address pattern. Optionally, it layers on BYOK enrichment from Hunter.io and/or People Data Labs, and a Claude Haiku 4.5-scored buying-intent read of the business's own crawled site text.
Because the source data is a business's own public web presence (an OSM tag or a customer-supplied name/domain) rather than a valued financial record, the data this actor produces supports outreach-targeting and pipeline-building use cases, not valuation or transaction-monitoring ones. Three concrete uses fit the actual fields it returns: (1) Sales development teams building a first-touch outreach list from a target territory — run Mode B against a bounding box covering, say, a metro business district, and get back businesses with a live website, any emailsFound, and an emailPlausible flag to filter out dead-end contacts before an SDR ever touches the list. (2) Marketing operations teams enriching an existing CRM export — feed a seed list of account names/domains already sitting in a spreadsheet or CRM (Mode A) to attach verified-plausible contact emails and, when BYOK keys are supplied, deeper Hunter.io/People Data Labs firmographic data, without paying this actor's own price for enrichment services the customer already has a separate account for. (3) Growth/RevOps teams prioritizing outbound sequencing by buying-intent signal — enable includeIntentScore to get a 0–100 heuristic score (with a mandatory disclaimer that it is a heuristic LLM read of public text, never a verified fact) derived from hiring-page, funding-news, and tech-stack signals visible on the business's own site, letting reps triage a long list into "likely warmer" vs. "likely colder" without manually reading every homepage.
What this actor is deliberately not built for: it has no monetary value field populated (value_native, value_currency, and value_usd_normalized are always null per its own dataset schema — "Not applicable to this actor"), so it is not a deal-size or contract-value tool. It also has no registry-style status lifecycle — there is no tender-closed, listing-updated, or similar event a business's own website exposes the way a government registry does — so it is not a monitoring tool for change-over-time on a fixed set of records; its own CHANGELOG documents this as a deliberate design decision rather than a gap.
Technical Features & V2 Architecture Highlights
Cross-run lead deduplication via a named key-value store. Per CHANGELOG.md, src/state.ts opens a NAMED key-value store — Actor.openKeyValueStore('actor-18-b2b-lead-magnet-seen-leads') — that persists which leads (identified by record_id) have already been discovered and charged for, across runs of this actor. This is real cross-run state, not an in-memory or single-run cache.
skipKnownLeads — what it actually does. Per the actor's own input_schema.json, when skipKnownLeads is enabled, "a lead already discovered (and charged for) in a prior run of this Actor is skipped before the enrichment waterfall runs — no repeat website crawl, no repeat BYOK/intent-score calls, and no repeat basic_lead/enriched_lead charge for the same business." Identity is a stable id derived from the OSM id (Mode B) or a normalized name+domain hash (Mode A), persisted in the named key-value store described above. Left off (the default), every run performs a full re-enrichment — useful when a business's own site content may have changed since the last run.
is_new is a real, populated field — not the richer classification you'll see on registry-style actors in this fleet. The dataset schema documents is_new as true if this exact business (by OSM id, or normalized name+domain for seed-list leads) was never seen in a prior run, false if it was — tracked in the named key-value store regardless of whether skipKnownLeads is enabled (that flag only controls whether an already-known lead is skipped from re-processing, not whether it is tracked at all). Per CHANGELOG.md 1.1.0, this field was previously always null and is now populated for real. Critically, this actor's own dataset schema is explicit that it does not implement the richer NEW_LISTING/STATUS_CHANGE/UPDATED/CLOSED delta-classification taxonomy some other actors in this fleet use: "a business's own listing has no observable status this actor tracks" — just seen-or-not-seen.
event_type is a fixed constant here, not a set of states. The dataset schema's own description for event_type reads: "Always NEW_LISTING — this actor has no cross-run delta-tracking concept." Every record this actor emits carries event_type: "NEW_LISTING"; there is no UPDATED or CLOSED value it ever writes, and per the CHANGELOG's own "Not added (and why)" section, that registry-style delta engine was deliberately not built for this domain: "a business's own web presence has no observable 'status' field the way a government tender or gazette entry does."
18-field base envelope, confirmed by this actor's own CHANGELOG. CHANGELOG.md 1.1.0 explicitly refers to is_new as "part of the 18-field UMS envelope" — confirming this actor shares the fleet's standard 18-field universal metadata shell (record_id, event_type, scraped_at, is_new, source_url, recipient_or_defendant_name, entity_identifier_native, value_native, value_currency, value_usd_normalized, effective_date_iso, publish_date_iso, category_or_type, status_or_estado, awarding_or_regulating_agency, jurisdiction, source_document_url, reference_number) on top of which this actor adds ten domain-specific fields (discoverySource, website, emailsFound, emailPlausible, emailPlausibilityMethod, websiteContentUnavailable, byokEnrichment, intentScore, intentScoreRationale, intentScoreDisclaimer) — 28 total fields per record.
Compliance-by-construction discovery. Discovery Mode B queries OpenStreetMap's public overpass-api.de mirror, which the input schema itself flags as "fair-use only — budget a self-hosted Overpass instance for production volume." Google Maps is excluded from the discovery layer entirely — not rate-limited or minimized, excluded — because of the ToS conflict described above. Per the README, "No CAPTCHA-solving, no fingerprint spoofing, no WAF/OAuth-gate bypass anywhere in this Actor," and a JS-rendered single-page site that can't be read from server-delivered HTML degrades to websiteContentUnavailable: true rather than escalating to a headless browser — a deliberate compliance-posture choice, not a missing feature.
BYOK enrichment never touches this actor's own PPE price. When hunterApiKey and/or peopleDataLabsApiKey are supplied, the actor calls each provider's API using the customer's own key, and that provider bills the customer's account directly — never this actor's own metered price. The byokEnrichment output field is null whenever neither key was supplied.
Input Schema & JSON Configuration Example
| Field | Type | Default | Description |
|---|---|---|---|
discoveryMode | string (enum: seedList, osmOverpass) | seedList | seedList (Mode A): enrich the company names/domains you supply directly - zero discovery-layer risk. osmOverpass (Mode B): discover candidate businesses from OpenStreetMap's Overpass API within a bounding box (ODbL-licensed - Google Maps is intentionally excluded from discovery because its Maps/Earth Additional ToS and Maps Platform ToS both prohibit building a business-listings/mailing-list database from Maps content). |
seedList | array | [] | Company names or website domains/URLs to enrich directly. Required (non-empty) when discoveryMode is "seedList". Mixed entries are fine - each is heuristically read as either a bare name ("Acme Corp") or a domain/URL ("acme.com", "https://acme.com"). |
overpassBbox | string | (none) | "south,west,north,east" in decimal degrees, e.g. "50.70,-1.90,50.90,-1.30". Required when discoveryMode is "osmOverpass". Queries the public overpass-api.de mirror, which is fair-use only - budget a self-hosted Overpass instance for production volume. |
maxLeads | integer (min 1, max 5000) | 50 | Hard cap on how many candidates are enriched and charged this run. |
includeIntentScore | boolean | false | When enabled, each lead gets one Claude Haiku 4.5 call scoring hiring-page, funding-news, and tech-stack signals read only from the business's own crawled site text (always paired with a mandatory disclaimer field - a heuristic read of public text, never a verified fact). Bills the enriched_lead PPE event ($0.015/record) instead of basic_lead ($0.002/record). Requires this Actor's own ANTHROPIC_API_KEY environment variable to be configured on the Actor - this is the operator's own compute cost (priced into the Enriched Lead rate), not a customer BYOK field. |
hunterApiKey | string (secret) | (none) | Your own Hunter.io API key. When supplied, this actor calls Hunter.io's domain-search endpoint using YOUR key - Hunter.io bills your own account directly, never this actor's own PPE price. |
peopleDataLabsApiKey | string (secret) | (none) | Your own People Data Labs API key, used and billed the same way as hunterApiKey - your own account is charged by People Data Labs directly. |
skipKnownLeads | boolean | false | When enabled, a lead already discovered (and charged for) in a prior run of this Actor is skipped before the enrichment waterfall runs - no repeat website crawl, no repeat BYOK/intent-score calls, and no repeat basic_lead/enriched_lead charge for the same business. Identity is a stable id derived from the OSM id (Mode B) or normalized name+domain (Mode A), persisted in this Actor's own key-value store across runs. Leave off (default) for a full re-enrichment on every run, e.g. if a business's own site content may have changed since last time. |
No fields are marked required at the schema level (conditional requirements — seedList for Mode A, overpassBbox for Mode B — are enforced by description/runtime logic, not the JSON Schema required array).
Example configuration — Mode A (seed list) with intent scoring and delta mode enabled:
{"discoveryMode": "seedList","seedList": ["acme.com", "Beta Consulting LLC", "https://gamma-industries.example"],"maxLeads": 100,"includeIntentScore": true,"skipKnownLeads": true}
Example configuration — Mode B (OSM Overpass discovery), basic tier only:
{"discoveryMode": "osmOverpass","overpassBbox": "50.70,-1.90,50.90,-1.30","maxLeads": 200,"includeIntentScore": false,"skipKnownLeads": true}
Output Dataset Sample & Data Dictionary
| Field | Type | Description |
|---|---|---|
record_id | string | osm:<type>/<id> for OSM-discovered leads; a deterministic seed:<hash> for seed-list leads - stable across runs for the same input. |
event_type | string | Always NEW_LISTING - this actor has no cross-run delta-tracking concept. |
scraped_at | string | ISO-8601 timestamp of this enrichment. |
is_new | boolean | null | true if this exact business (identified by OSM id, or normalized name+domain for seed-list leads) was never seen in a prior run of this Actor; false if it was. Tracked in this Actor's own key-value store regardless of the skipKnownLeads input - that flag only controls whether an already-known lead is skipped, not whether it's tracked. Unlike a registry-monitoring actor, this is a simple seen/not-seen signal, not a richer NEW_LISTING/STATUS_CHANGE/UPDATED/CLOSED classification - a business's own listing has no observable status this actor tracks. |
source_url | string | null | The business's own website, when known. |
recipient_or_defendant_name | string | null | Business Name (fleet-standard UMS field name; holds the discovered/supplied business's name). |
entity_identifier_native | string | null | Raw OSM type/id (e.g. node/48213456) for OSM discovery; null for seed-list leads (no native source id exists for a customer-typed name). |
value_native | string | null | Not applicable to this actor - always null. |
value_currency | string | null | Not applicable to this actor - always null. |
value_usd_normalized | number | null | Not applicable to this actor - always null. |
effective_date_iso | string | null | Not applicable to this actor - always null. |
publish_date_iso | string | null | Not applicable to this actor - always null. |
category_or_type | string | null | business_listing_osm or business_listing_seed. |
status_or_estado | string | null | Not applicable to this actor - always null. |
awarding_or_regulating_agency | string | null | Not applicable to this actor - always null. |
jurisdiction | string | OSM for Overpass discovery; GLOBAL for seed-list leads (no single jurisdiction applies). |
source_document_url | string | null | Not applicable to this actor - always null. |
reference_number | string | null | Not applicable to this actor - always null. |
discoverySource | string (enum: seedList, osm) | Which discovery mode produced this lead. |
website | string | null | The resolved website URL used for the crawl. |
emailsFound | array of string | mailto: links and regex-matched addresses found on the crawled page(s). |
emailPlausible | boolean | null | true when the domain has a non-null MX record set (dns.promises.resolveMx). null when no domain was available to check. |
emailPlausibilityMethod | string | null (enum: mx_record_present, null_mx, mx_lookup_failed, no_domain, null) | Which path produced the emailPlausible verdict. |
websiteContentUnavailable | boolean | true when the site could not be fetched, is disallowed by robots.txt, or looks like a client-side-rendered SPA with no server-delivered content - this actor never escalates to a headless browser. |
byokEnrichment | object | null | null when neither hunterApiKey nor peopleDataLabsApiKey was supplied. Otherwise per-provider used/data/error using the CUSTOMER's own key - billed by that vendor to the customer directly, never to this actor's own PPE price. Sub-fields: hunterIo (object | null), peopleDataLabs (object | null). |
intentScore | number | null | 0-100 heuristic buying-intent score from Claude Haiku 4.5, only when includeIntentScore was enabled and the model call succeeded. |
intentScoreRationale | string | null | Free-text rationale the model gave for the score above. |
intentScoreDisclaimer | string | null | Mandatory whenever intent scoring was attempted - never omitted. States this is a heuristic LLM read of public text, not a verified fact. |
Sample dataset record (Mode A, seed-list lead, includeIntentScore: true, no BYOK keys supplied):
{"record_id": "seed:3f9a1c2b8e7d4f0a","event_type": "NEW_LISTING","scraped_at": "2026-09-08T14:00:00.000Z","is_new": true,"source_url": "https://acme.com","recipient_or_defendant_name": "Acme","entity_identifier_native": null,"value_native": null,"value_currency": null,"value_usd_normalized": null,"effective_date_iso": null,"publish_date_iso": null,"category_or_type": "business_listing_seed","status_or_estado": null,"awarding_or_regulating_agency": null,"jurisdiction": "GLOBAL","source_document_url": null,"reference_number": null,"discoverySource": "seedList","website": "https://acme.com","emailsFound": ["contact@acme.com"],"emailPlausible": true,"emailPlausibilityMethod": "mx_record_present","websiteContentUnavailable": false,"byokEnrichment": null,"intentScore": 62,"intentScoreRationale": "Careers page lists 3 open roles; HubSpot tag present on homepage.","intentScoreDisclaimer": "Heuristic LLM-derived estimate from public website text only. Not a verified fact."}
Multi-language Integration Snippets
cURL
curl "https://api.apify.com/v2/acts/stefano_seggio~actor-18-b2b-lead-magnet/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-X POST \-H "Content-Type: application/json" \-d '{"discoveryMode": "seedList","seedList": ["acme.com", "Beta Consulting LLC", "https://gamma-industries.example"],"maxLeads": 100,"includeIntentScore": true,"skipKnownLeads": true}'
Python (apify-client)
from apify_client import ApifyClientclient = ApifyClient(token="<APIFY_TOKEN>")run_input = {"discoveryMode": "seedList","seedList": ["acme.com", "Beta Consulting LLC", "https://gamma-industries.example"],"maxLeads": 100,"includeIntentScore": True,"skipKnownLeads": True,}run = client.actor("stefano_seggio/actor-18-b2b-lead-magnet").call(run_input=run_input)for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["recipient_or_defendant_name"], item["website"], item["intentScore"])
Node.js (apify-client)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<APIFY_TOKEN>' });const runInput = {discoveryMode: 'seedList',seedList: ['acme.com', 'Beta Consulting LLC', 'https://gamma-industries.example'],maxLeads: 100,includeIntentScore: true,skipKnownLeads: true,};const run = await client.actor('stefano_seggio/actor-18-b2b-lead-magnet').call(runInput);const { items } = await client.dataset(run.defaultDatasetId).listItems();items.forEach((item) => {console.log(item.recipient_or_defendant_name, item.website, item.intentScore);});
Pricing Model Explanation
This actor bills on a Pay-Per-Event (PPE) model with three named events:
| Event | Price | What triggers it in this actor |
|---|---|---|
apify-actor-start | $0.00005 | Standard Apify per-run start fee, charged once when the actor run begins - independent of how many leads it goes on to process. |
basic_lead | $0.002/record | Charged for each lead that completes discovery, the website crawl, and the DNS/MX email-plausibility check - the full waterfall without the Claude intent-scoring step. |
enriched_lead | $0.015/record | Charged instead of basic_lead for each lead that also gets the Claude Haiku 4.5 buying-intent read (triggered by setting includeIntentScore: true). It covers everything basic_lead does, plus one model call per lead. |
Why two tiers, and what actually separates them. Per this actor's own README, the two tiers are never blended: basic_lead covers "Discovery + website crawl + DNS/MX check," while enriched_lead covers "Everything in basic_lead plus the Claude intent score." The split is not "old vs. new" or "two different sub-sources" — every lead in a given run goes through the identical discovery-and-crawl waterfall regardless of tier; the only thing that moves a lead from basic_lead to enriched_lead is whether includeIntentScore triggered a Claude Haiku 4.5 call for that specific record. The README states this plainly: "The LLM step costs roughly 7x the rest of the waterfall combined - kept as a separate tier so a basic run never silently absorbs that cost." In other words, the pricing tier directly mirrors the one real cost driver in this actor's architecture: whether or not an LLM call happened for that lead.
BYOK enrichment (Hunter.io, People Data Labs) is billed outside this actor entirely. When hunterApiKey and/or peopleDataLabsApiKey are supplied, those providers bill the customer's own account directly for that usage — it is never folded into basic_lead or enriched_lead pricing, and using BYOK enrichment does not change which of the two tiers a lead is charged at.
What skipKnownLeads means for your bill. When skipKnownLeads: true is set on a recurring run, a lead already discovered (and already charged for) in a prior run of this actor is skipped before the enrichment waterfall runs at all — no repeat website crawl, no repeat BYOK or intent-score calls. Concretely, that means an already-known, unchanged business is never delivered as a dataset record and never triggers a basic_lead or enriched_lead chargeable event on that run — it is not billed at $0, it simply never becomes a billable event in the first place, because the actor's own named key-value store recognized it and routed it out of the waterfall before any chargeable work happened. The apify-actor-start fee is unaffected by this and is still charged once per run regardless of how many leads end up being skipped.