Real Estate & Clinic Leads: Decision-Maker Pack
Pricing
from $20.00 / 1,000 enriched leads
Real Estate & Clinic Leads: Decision-Maker Pack
Turn scraped business data for real estate offices or clinics into ranked leads: merges duplicates across sources, picks the named decision-maker from your contacts, extracts license, brokerage or specialty, and gives each lead a READY/REVIEW/WEAK verdict. No LLM.
Pricing
from $20.00 / 1,000 enriched leads
Rating
0.0
(0)
Developer
Turgay NANTA
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a month ago
Last modified
Categories
Share
Real Estate Leads and Clinic Leads: Find the Decision-Maker in Your Scraped Business Data
Scraped lead lists for realtors and clinics look big and convert badly. The same brokerage appears three times from three sources, most rows only have info@ or appointments@, and nobody can tell which of the 800 contacts is the managing broker or the practice owner who actually signs off.
This Actor turns raw, multi-source business records for one vertical (real estate or healthcare clinics) into a ranked decision-maker lead pack. It merges fragments of the same business into one record, picks the most likely decision-maker (a named broker, owner, manager or chief physician when your data contains one), extracts vertical-specific attributes such as brokerage keyword, license number or clinic specialty, and gives every lead a READY / REVIEW / WEAK send-readiness verdict and a 0-100 priority.
- Who it is for: lead generation agencies, SDR teams and marketers selling to real estate offices or clinics, and anyone who already has scraped data and needs to know whom to contact first.
- What it costs: $0.30 per 100 input records plus $0.02 per lead in the output. The built-in example costs about $0.32. See Pricing.
- One click: all fields are optional; an empty input runs a small real estate example so you can see the output format.
- No LLM: fully deterministic rules, so the same input always gives the same output.
Not a scraper by itself. This Actor is the qualification layer that runs after a scrape: you bring records (pasted, or an Apify dataset), or you let it call an upstream Google Maps scraper that is billed separately. It works best when your records include people contacts (
contactswith name, title and email).
What one output lead looks like
This is the real output of the built-in example (two fragments of the same brokerage merged into one lead):
{"priority": 100,"business": "Acme Realty Downtown Office","website": "acmerealty.com","phone": "+15125550142","address": "100 Congress Ave, Austin, TX","vertical": "Real Estate","decision_maker_name": "Jane Carter","decision_maker_title": "Managing Broker","decision_maker_email": "jane.carter@acmerealty.com","vertical_attributes": "brokerage: realty · license_no: TX-0654321 · office_or_agent: office","send_readiness": "READY","send_readiness_reason": "named decision-maker + personal email + vertical attribute filled","decision_maker": {"name": "Jane Carter", "title": "Managing Broker", "email": "jane.carter@acmerealty.com", "source": "title_match", "role_account": false},"vertical_fields": {"brokerage": "realty", "license_no": "TX-0654321", "office_or_agent": "office"},"socials": [{"platform": "instagram", "url": "instagram.com/acmerealty"}],"all_emails": ["info@acmerealty.com"]}
At a glance
| Verticals | Real Estate (default) or Healthcare / Clinic |
| Input | Raw records (records), an Apify dataset (datasetId), or search terms for an upstream Google Maps scraper (searchTerms) |
| Output | One lead per unique business + a _summary row with a top-10 "reach these first" list |
| Key columns | priority, business, decision_maker_name, decision_maker_title, decision_maker_email, vertical_attributes, send_readiness |
| Merging | Multi-key: shared website, phone or email joins fragments; a name alone never merges two businesses |
| Verdict | READY, REVIEW or WEAK, each with a plain-English reason |
| Speed | Pure Python, no browser (except in the optional upstream search) |
| Runs on | Apify Console, API, schedules, n8n, Make, Zapier, AI agents via MCP |
Quick start (2 minutes)
- Click Start with the default input to see a complete Real Estate lead from the example records.
- For your own data: run a Google Maps, directory or website scraper, copy the dataset ID from its Storage tab, and paste it into connected dataset ID.
- Pick the vertical (Real Estate or Healthcare / Clinic) and click Start.
- Open the Lead Table view in the Dataset tab and sort by
priority.
No data yet? Put terms such as real estate agency Austin into search terms. The Actor then calls an upstream Google Maps scraper for you (billed separately in your Apify account) and qualifies the result.
When more than one source is filled in, the Actor uses dataset ID first, then search terms, then records. The example records therefore never override your dataset or search.
Why people use it
A generic scraper gives you what a listing shows. That creates four problems for anyone selling to real estate offices or clinics:
- Fragments. The Maps listing, the website crawl and a directory entry of the same business are three rows. Each has part of the picture.
- No person. The listing has
info@orappointments@. The person who decides (the broker, the owner, the practice manager) is somewhere else in your data, or not there at all. - No segmentation. You cannot tell a brokerage office from a solo agent, or an orthodontics practice from a general dental clinic, without reading every row.
- No order. Hundreds of rows with no ranking means you either review by hand or email everyone.
This Actor fixes all four in one pass and tells you exactly why each lead got its verdict.
How it works
- Reads any record shape. Field names are auto-detected:
- name:
name,title,businessName,company,placeName,practiceName - website:
website,url,site,domain - phone:
phoneUnformatted,internationalPhoneNumber,phone,phoneNumber,telephone,tel,mobile - country:
countryCode,country_code,countryIso - address:
address,fullAddress,location - emails:
emails,email,emailList,contactEmails - socials:
socials,social,socialMedia,socialLinks - people:
contacts,people,team,staff,namedContacts(each withname,titleorrole,email) - free text:
rawTextordescription; search context:searchTermorquery
- name:
- Normalizes fields. Websites become a bare domain, emails are lowercased and validated, social links are reduced to canonical profile URLs (Facebook, Instagram, X/Twitter, LinkedIn, YouTube, TikTok). Phones get an international
+format when the number already has one or the record has a knowncountryCode; otherwise the digits are kept and no country code is invented. - Merges fragments. Records that share a website, a phone number or any email (including a contact's email) are joined into one business, and a record that carries two of these keys bridges both groups. Two businesses that only share a name stay separate.
- Picks the decision-maker in this order:
- a contact whose title matches the vertical's decision-maker words (
title_match) - otherwise a contact with a personal, non-role email (
personal_email) - otherwise the first named contact (
named_contact) - otherwise the best business email, with no name (
business_email)
- a contact whose title matches the vertical's decision-maker words (
- Extracts vertical attributes (see the table below).
- Assigns a send-readiness verdict and a priority score.
- Writes a summary with verdict counts and a top-10 "reach these first" list.
Vertical rules
| Real Estate | Healthcare / Clinic | |
|---|---|---|
| Decision-maker title words | broker, owner, principal, manager, director, founder | owner, manager, office manager, chief physician, dr |
| Attribute 1 | brokerage: brand or type keyword found in name or address (realty, real estate, remax, century 21, coldwell, keller) | specialty: keyword found in name, search term or text (ortho, implant, dental, pediatri) |
| Attribute 2 | license_no: code after "License No", "License #" or "Reg" in name, address or text | booking_channel: which of phone, social (Instagram or Facebook) and web are available |
| Attribute 3 | office_or_agent: office when the name contains office, realty, remax or century; otherwise agent |
The keyword lists also include Turkish terms, because the Actor was first built for the Turkish market. brokerage and specialty return the matched keyword, not a cleaned company name.
Send-readiness verdict
| Verdict | When | What to do |
|---|---|---|
READY | Named decision-maker with a personal (non-role) corporate or free-provider email, and at least one vertical attribute | Contact first |
REVIEW | Personal corporate email without a name or attribute, a role inbox only (info@, appointments@), or other partial data | Research the person before a cold campaign |
WEAK | No decision-maker email, or an invalid or disposable address | Call, or skip for email |
Priority score (0-100)
| Component | Points |
|---|---|
| Verdict READY / REVIEW / WEAK | 50 / 25 / 5 |
| Named decision-maker | 25 |
| Personal (non-role) email | 15 |
| Vertical attributes filled | 5 each, up to 10 |
Use cases by profession
Lead generation agencies
You scrape "real estate agency" for a client city and deliver hundreds of rows. Run this Actor first: fragments collapse into one lead each, the client sees a named broker where your data had one, and every row has a verdict with a reason. The deliverable looks like research, not a dump.
SDR and outbound teams selling to realtors
Load only READY leads into your sequencer for the first wave. Send REVIEW leads to a people-search step to find the broker behind info@. Keep WEAK leads for calls. Use office_or_agent to split messaging between brokerages and individual agents.
Proptech and mortgage partnerships
Brokerage offices with a license number and a named managing broker are the partners worth a meeting. Sort by priority and filter vertical_fields.license_no to find them.
Dental, medical and aesthetic clinic suppliers
Switch the vertical to Healthcare / Clinic. Leads get a specialty keyword (for example ortho or implant) for segmentation and a booking_channel list that shows whether the clinic books by phone, social or web, which is useful when you sell booking or marketing services.
Healthcare marketing agencies
Clinics with only appointments@ and a social profile are a clear pitch for a better web booking flow. The combination of booking_channel and the verdict reason finds them without manual review.
CRM hygiene before import
Even if you do not need the verdicts, the merge alone is valuable: one record per business with all emails, socials and contacts combined, ready for HubSpot, Pipedrive or a spreadsheet.
Input
All fields are optional. With an empty input, the example records run in the Real Estate vertical.
| Field | Type | Default | Description |
|---|---|---|---|
vertical | select | Real Estate | emlak = Real Estate, klinik = Healthcare / Clinic (the internal keys are Turkish). |
records | array | small example | Raw business records from any scraper or your own list. |
datasetId | string | none | ID of an Apify dataset with raw records. Used instead of records when set. |
searchTerms | array | none | Terms for the upstream Google Maps scraper compass/crawler-google-places (with contact scraping on). Used instead of records when set. Billed separately by that Actor. |
maxPlaces | integer | 50 | Places per search term in search mode. |
Example: qualify an existing dataset
{"vertical": "emlak","datasetId": "YOUR_DATASET_ID"}
Example: paste records with people contacts
{"vertical": "klinik","records": [{"title": "Acme Orthodontics Clinic", "url": "https://acmeortho.com","phone": "+1 212 555 1234", "emails": ["appointments@acmeortho.com"],"social": ["instagram.com/acmeortho"]},{"name": "Acme Ortho Center", "website": "acmeortho.com","contacts": [{"name": "Dr. Jane Carter", "title": "Chief Physician", "email": "jane.carter@acmeortho.com"}],"rawText": "Implant and orthodontics specialist clinic"}]}
The two rows share the website, so they become one lead. The chief physician is chosen as the decision-maker, specialty is ortho, booking_channel is phone, social and web, and the verdict is READY.
Example: start from a search
{"vertical": "emlak","searchTerms": ["real estate agency Austin TX"],"maxPlaces": 50}
Output
Lead records
| Field | Description |
|---|---|
priority | 0-100; contact the highest first |
business | Business name (the longest name among merged fragments) |
website, phone, address | Normalized contact fields |
vertical | Real Estate or Healthcare / Clinic |
decision_maker | name, title, email, source (title_match, personal_email, named_contact, business_email) and role_account |
decision_maker_name, decision_maker_title, decision_maker_email | Flat copies for the table view |
vertical_fields | Real estate: brokerage, license_no, office_or_agent. Clinic: specialty, booking_channel |
vertical_attributes | One readable line with the filled attributes |
socials | Canonical profiles as {platform, url} |
all_emails | All business emails found on the merged records (contact emails appear under decision_maker) |
send_readiness, send_readiness_reason | Verdict and its reason |
The Lead Table view shows priority, business, the three decision-maker columns, vertical_attributes and send_readiness. Export as CSV, Excel, JSON or HTML.
Summary row (last row)
{"_summary": {"vertical": "Real Estate","total_leads": 1,"with_decision_maker": 1,"named_decision_maker": 1,"verdict_distribution": {"READY": 1},"ready_to_send": 1,"reach_first_list": [{"rank": 1, "business": "Acme Realty Downtown Office", "priority": 100, "decision_maker": "Jane Carter", "verdict": "READY"}]}}
This is the summary of the built-in example. Your run reports its own numbers.
Pricing
Pay per event, no subscription. Current prices are always shown on the Pricing tab; at the time of writing they are:
| Event | When it is charged | Price |
|---|---|---|
actor-start | Once per run with input data | $0.0001 |
lead-processed-100 | Per started block of 100 input records (at least one per run) | $0.30 |
enriched | Per lead in the output (after merging) | $0.02 |
Fragments are merged before the per-lead charge, so three rows of the same business cost one lead. A run with no input data fails with a clear message and is not charged.
| Input records | Leads after merge (example) | Cost |
|---|---|---|
| 2 (built-in example) | 1 | $0.0001 + $0.30 + $0.02 = $0.3201 |
| 100 | 80 | $0.0001 + $0.30 + $1.60 = $1.9001 |
| 250 | 200 | $0.0001 + $0.90 + $4.00 = $4.9001 |
| 1,000 | 850 | $0.0001 + $3.00 + $17.00 = $20.0001 |
In search mode, the upstream Google Maps scraper bills its own usage in your Apify account, in addition to the prices above.
Integrations
Chain it after your scraper
In Apify Console open your Maps or directory scraper, go to Integrations, add Run another Actor, pick this Actor, and pass the scraper's default dataset ID as datasetId. Every scrape is then qualified automatically.
API
curl -X POST "https://api.apify.com/v2/acts/enezli~vertical-lead-pack/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"vertical": "emlak", "datasetId": "YOUR_DATASET_ID"}'
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_TOKEN")run = client.actor("enezli/vertical-lead-pack").call(run_input={"vertical": "emlak", "datasetId": "YOUR_DATASET_ID"})ready = [r for r in client.dataset(run["defaultDatasetId"]).iterate_items()if r.get("send_readiness") == "READY"]print(len(ready), "leads ready to contact")
Schedules
Schedule your scraper (for example weekly) with the integration above. Each new scrape arrives qualified. This Actor itself does not compare runs; it qualifies whatever records it receives.
n8n, Make, Zapier
Use the Apify node or app: Run Actor, then Get dataset items, then route by send_readiness (READY to your email tool, REVIEW to a research step, WEAK to a call list).
AI agents (MCP)
Available through the Apify MCP server, so assistants such as Claude or Cursor can call it with a dataset ID and read back the ranked leads.
Tips for best results
- Bring people data. Named decision-makers come from
contacts(orpeople,team,staff). A website crawl of "About" or "Team" pages is the best source. Google Maps data alone rarely has names, so most Maps-only leads end asREVIEW. - Keep
countryCodein your records so phones get an international format. - Merge several sources in one run. Put Maps output and website crawl output together into
records; cross-source merging is where the value appears. - Pick the vertical that matches your data. The clinic rules on real estate data (or the reverse) give empty attributes and weaker verdicts.
- Check
decision_maker.source.title_matchis the strongest signal;business_emailmeans no person was found.
Limitations
- The Actor does not visit websites or look up people. It only uses what your records contain (or what the upstream scraper returns in search mode).
- Decision-maker detection is keyword based. Titles outside the listed words are not matched by title, though a contact with a personal email is still picked in the next step.
- In Real Estate,
office_or_agentis always filled (agentwhen no office word is in the name), so it always counts as one filled attribute. - There is no live email verification (no MX or SMTP check); the email type comes from the address itself.
- Specialty keywords are a short list. Specialties that are not on it return empty.
- Two verticals only: Real Estate and Healthcare / Clinic.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Run fails with "No input" | No records, datasetId or searchTerms reached the Actor | Provide one of them |
All leads are REVIEW or WEAK | Records have no people contacts | Add a website or team-page crawl as a source |
| The example ran instead of my dataset | Older versions preferred records over datasetId | Current version uses the dataset first; re-run |
| Two branches merged into one lead | They share a phone, website or email in the source data | Check for a shared central phone or brand website |
Phones without + | No country code in the number and no countryCode | Keep countryCode in your scraper output |
license_no is empty | The license is not written with "License No", "License #" or "Reg" | Add it to rawText in that form, or leave it empty |
FAQ
Is this a scraper?
Not by itself. It qualifies records you already have. In search mode it calls the upstream Google Maps scraper compass/crawler-google-places, which is billed separately.
Where do decision-maker names come from? Only from the people contacts in your records. The Actor never guesses a name.
Does it use AI? No. All rules are deterministic Python.
Which verticals are supported? Real Estate and Healthcare / Clinic.
Do I pay for duplicates? No. Records are merged first; the per-lead charge applies to merged leads.
Can I use it for GDPR-sensitive outreach? It processes only the data you provide. You remain responsible for a lawful basis for contacting people; role inboxes and personal addresses are flagged separately to help you apply your policy.
I found a bug or need a vertical. Open an issue on the Issues tab. A sample input speeds up the fix.
Trademarks
This Actor is not affiliated with, endorsed by, or connected to Google Maps. All product names are trademarks of their respective owners.