Track New People at Your Target Accounts Every Week
Schedule B2B Leads Finder in monitor mode so each weekly run returns only people you have not been sent before, and never bills the same person twice.
The actor referenced in this article. Pay only for results delivered.
Most account lists are built once and then go stale. A new head of marketing joins one of your target companies, and the first you hear of it is when a rival’s sales rep has already booked the call. People who just started a job are worth reaching early: they are setting budgets, picking vendors and looking for quick wins.
Try it live: B2B Leads Finder, Like Apollo. Pay per result delivered. Failed and empty results are never charged.
The B2B Leads Finder has a switch for this, monitorMode. With it on, the actor remembers every person it has delivered to your Apify account (up to 50,000) and each later run returns only people you have not been sent before. Put it on a weekly schedule and you get a short list of new names at your accounts instead of the same list again.
What you get and who it is for
Each weekly run writes person rows with the same fields as a normal run:
| Field | What it holds |
|---|---|
company, domain | The account the person was found for |
name, job_title, linkedin_url | The person and their LinkedIn headline, from search results |
title_match | true when the headline matches one of your job titles |
email, email_confidence, email_note | A business email, with found, pattern_matched or guessed saying how it was made |
source | linkedin-serp or website-scrape (the company’s own team page) |
charged, scraped_at | Whether the row was billed, and when it was written |
Plus a free summary row at the end. In monitor mode, already_delivered_in_earlier_run in the summary counts the people the run skipped because you already have them, and monitor is true.
This is for account executives watching a named list of accounts, ABM teams who want a trigger for outreach, and anyone who already built a contact list once and wants to keep it current without paying for the same people every week.
Why repeat runs need monitor mode
We run a small daily check on stripe.com with monitor mode off and maxLeadsPerCompany at 1. Each day it returns three people, because a search page already fetched is delivered in full. On October 4, all three people it returned had already been delivered by our October 1 run on Stripe, and all three were charged again. On October 5 and October 6 it returned three different people each day.
Two lessons come from that. Without monitor mode, a repeat run pays again for people you already hold. And web search does not return the same people in the same order every day, so a run can surface someone who was always there but did not show up last time. Monitor mode fixes the first problem. The second one is why “new to you” is not the same as “just hired”.
The input
{
"companies": ["stripe.com", "notion.so", "linear.app", "vercel.com", "supabase.com"],
"jobTitles": ["Head of Marketing", "VP Marketing", "CMO"],
"maxLeadsPerCompany": 5,
"scrapeWebsite": true,
"monitorMode": true
}
monitorModeis the switch this job depends on. It defaults tofalse.companiestakes up to five domains per run. For more accounts, save one task per group of five. Use domains rather than names, so emails can be built.jobTitlesputs matching people first and labels themtitle_match: true. It does not drop everyone else: people outside those titles are delivered and charged too.maxLeadsPerCompanycaps how many people each company adds per run, and a run delivers at most 25 in total. A low number keeps each weekly run small and lets the backlog clear over several weeks.- Keep
companiesandjobTitlesthe same from run to run. Changing them makes it a different search.
What the output looks like
We do not have a monitor mode run of our own to show, so these rows come from the daily stripe.com check described above, runs 5pAvvhY9fRI5mKdPH (October 5, 2026) and YYvtu2GWhJOFQgvcB (October 6). They are the kind of rows a weekly run hands you: people the previous run did not include. Names, emails and profile URLs are masked here.
[
{
"company": "Stripe",
"domain": "stripe.com",
"name": "T*** M***",
"job_title": "Head of Latin America Regulatory at Stripe",
"linkedin_url": "https://www.linkedin.com/in/***",
"email": "t***.m***@stripe.com",
"email_confidence": "guessed",
"email_note": "Guess: first.last is the most common format and stripe.com publishes no staff address to learn from. Mailbox not verified, check before sending.",
"source": "linkedin-serp",
"scraped_at": "2026-10-05T09:00:40.659Z",
"charged": true
},
{
"company": "Stripe",
"domain": "stripe.com",
"name": "E*** M***",
"job_title": "Chief Revenue Officer | Payments & Link l Stripe",
"linkedin_url": "https://www.linkedin.com/in/***",
"email": "e***.m***@stripe.com",
"email_confidence": "guessed",
"source": "linkedin-serp",
"scraped_at": "2026-10-06T09:00:34.757Z",
"charged": true
},
{
"company": "Stripe",
"domain": "stripe.com",
"name": "F*** R***",
"job_title": "Stripe",
"linkedin_url": "https://www.linkedin.com/in/***",
"email": "f***.r***@stripe.com",
"email_confidence": "guessed",
"source": "linkedin-serp",
"scraped_at": "2026-10-06T09:00:34.955Z",
"charged": true
}
]
Note what is and is not there. None of these rows says when the person joined. A chief revenue officer at Stripe is a senior person worth knowing, but nothing in the row says they started last week. The third row’s headline is only the company name, so you cannot tell the role at all without opening the profile. Every email is guessed, with a note that the mailbox is not verified, because Stripe publishes no staff addresses.
A company check matters here too. In our October 1 run on notion.so, three people marked as CEO matches ran other businesses with Notion in their names. A monitor run on a short company name will keep turning up people like that, and each is “new” the first time.
Run it in Apify Console
- Open https://apify.com/themineworks/b2b-leads-finder and click Try for free.
- Enter up to five domains in Target companies and your roles in Job titles to target.
- Set Max leads per company to 5 and tick Monitor mode (only new people).
- Click Save as a new task and give it a name, such as
accounts-group-1. - Run the task once and check the summary row:
monitorshould betrue. - In the task, open Schedules, add a schedule with the cron expression
0 7 * * 1(Mondays at 07:00) and save. - Each Monday, open the run’s Output tab, or let an integration pick up the rows for you.
The first few runs work through each company’s backlog of people you have never been sent, so they are fuller. After that, runs get shorter and some return nobody.
Run it from Python
pip install apify-client
This script runs one group of accounts in monitor mode, flags rows that need a look, and appends the new people to a history file with the date they first appeared. Run it weekly from your own scheduler, or see the note after it to read an Apify-scheduled task instead.
import csv
import re
from datetime import date
from pathlib import Path
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
RUN_INPUT = {
"companies": ["stripe.com", "notion.so", "linear.app", "vercel.com", "supabase.com"],
"jobTitles": ["Head of Marketing", "VP Marketing", "CMO"],
"maxLeadsPerCompany": 5,
"scrapeWebsite": True,
"monitorMode": True,
}
HISTORY = Path("account_people_history.csv")
FIELDS = ["first_seen", "company", "domain", "name", "job_title", "title_match",
"linkedin_url", "email", "email_confidence", "review", "source"]
def review_flags(row):
flags = []
headline = re.sub(r"[]", "", row.get("job_title") or "").lower()
company = row["company"].lower()
if row.get("source") == "linkedin-serp":
i = headline.find(company)
before = headline[:i].split() if i >= 0 else []
if i < 0:
flags.append("company not in headline")
elif before and before[-1] not in {"at", "@", "of", "for", "in", "|"}:
flags.append("may be another company")
elif re.search(r"\b(inc|corp|llc|ltd|gmbh|pvt)\b", headline[i:].split("|")[0]):
flags.append("may be another company")
if headline.strip(" .") == company:
flags.append("headline is only the company name")
if re.search(r"\b(ex|former|formerly)\b", headline):
flags.append("headline mentions a past job")
if row.get("email_confidence") != "found":
flags.append("verify email" if row.get("email") else "no email")
return "; ".join(flags)
run = client.actor("themineworks/b2b-leads-finder").call(run_input=RUN_INPUT)
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
summary = next((i for i in items if i.get("_type") == "summary"), {})
if not summary.get("monitor"):
print("Warning: monitor mode was not active, rows may repeat earlier runs")
known = set()
if HISTORY.exists():
with HISTORY.open(newline="", encoding="utf-8") as f:
known = {(r["linkedin_url"] or r["email"]) for r in csv.DictReader(f)}
new_rows = []
for item in items:
if item.get("_type") or not item.get("charged"):
continue # report rows and free company inboxes
key = item.get("linkedin_url") or item.get("email")
if key in known:
continue # safety net if monitor memory was unavailable
item["first_seen"] = date.today().isoformat()
item["review"] = review_flags(item)
new_rows.append(item)
write_header = not HISTORY.exists()
with HISTORY.open("a", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=FIELDS, extrasaction="ignore")
if write_header:
writer.writeheader()
writer.writerows(new_rows)
print(f"{len(new_rows)} new people, "
f"{summary.get('already_delivered_in_earlier_run', 0)} skipped as already delivered")
for r in sorted(new_rows, key=lambda r: not r.get("title_match")):
tag = "MATCH" if r.get("title_match") else "other"
print(f"[{tag}] {r['company']}: {r.get('job_title', '')} | {r['review'] or 'clean'}")
The review column is there so the weekly list gets read, not just imported. On the daily Stripe rows above, it marks every row “verify email” and the third “headline is only the company name”. It also marks the chief revenue officer as “may be another company”, because the headline ends “Link l Stripe”: a false alarm, and the reason these are flags for a person rather than filters. On our October 1 Notion rows it marks all three wrong-company CEO matches as “may be another company”, and “headline mentions a past job” catches headlines like “Ex-TikTok”, which are worth a glance even when the past job was somewhere else. The local history check is a second line of defense: the actor says that if it cannot open its monitor memory, the run delivers everything and says so in the log, and the monitor check at the top catches the case where the switch was off.
If you prefer Apify’s own schedule, keep the task running there and read its latest run instead of starting one: replace the call line with run = client.task("YOUR_USERNAME~accounts-group-1").last_run(status="SUCCEEDED").get(), then read the dataset the same way.
Turn the list into an alert
A history file is fine for one person. For a team, send each run’s new rows somewhere they will be seen:
- Apify’s Google Sheets integration appends each run’s dataset to a sheet, which works well with a filter view on
title_match. - A webhook on the task can call your own endpoint when a run succeeds, which can post title matches to a Slack channel.
- Make, Zapier and n8n can pick up the dataset and create a task in your CRM for each
title_match: truerow, after a check of the company in the headline.
Keep the alert to title matches with a clean company check. The other rows are worth keeping in the history file, but they are not a reason to interrupt anyone.
What it costs
From October 13, 2026 the price is $6.10 per 1,000 leads on the Bronze plan, $4.95 on Silver and $4.00 on Gold and above, plus a flat $0.005 per run. Until October 12 it is $3.75, $3.50 and $3.00 per 1,000 leads with no run fee.
Monitor mode changes what you pay for over time, because you never pay for the same person twice:
- A backlog week: five companies at five leads each is 25 leads. On Bronze that is $0.1525 plus $0.005, about $0.16 a run.
- A quiet week: two new people is $0.0122 plus $0.005, about $0.02 on Bronze.
- A week with nobody new: no lead charges, only the $0.005 run fee.
- Ten accounts for a month: two tasks of five, run every Monday, is eight runs. If every run were a full backlog run, that would be 200 leads, $1.22 plus $0.04 on Bronze, $1.26 in all. Once the backlog clears, the same month costs a few cents plus $0.04 in run fees.
Limits worth knowing
- New to you, not newly hired. Monitor mode tracks what it has delivered to your account. A new row can be a new hire, a headline change or a profile that only just surfaced in search.
- The first runs are backlog. On a large company the actor works deeper through the roster run by run before later runs return only genuinely new profiles.
- Job titles rank, they do not filter. People outside your titles are delivered and charged. Keep
maxLeadsPerCompanylow. - Five companies and 25 leads per run. More accounts mean more tasks, each with its own schedule.
- Search lags real life. A headline is only as current as the person’s profile and the search engine’s copy of it, so a job change can take a few weeks to appear.
- Emails need checking. At large companies most addresses are
guessed. Verify before sending. Smaller accounts often publish real addresses, which a sweep of the company’s own site will find. - The data is personal. Names, titles and work emails fall under GDPR, CCPA and similar laws, and cold email has its own rules.
Related
Explore the scraper referenced in this article: inputs, outputs, and pricing, then run it on Apify.
Frequently asked questions
Does monitor mode tell me who was just hired? +
Not exactly. It returns people the actor has not delivered to your account before. Once the backlog for a company is worked through, that is mostly people newly visible in search: new hires, people who changed their headline, and profiles a search engine indexed late. Check the profile before you treat someone as a new hire.
Am I charged again for people I already have? +
No. With monitorMode on, people delivered by an earlier monitor mode run are skipped and not charged. A run that finds nobody new charges no leads, and from October 13, 2026 it still carries the $0.005 run fee.
Can I change the company list later? +
Keep the company list and job titles the same between runs, as the actor's own guidance says. For a different set of accounts, save a second task with its own list rather than editing the first one.
Do job titles filter out everyone else? +
No. Job titles rank the results: matches come first and are labeled title_match true, but people who do not match are still delivered and charged. Use maxLeadsPerCompany to cap how many people each company can add per run.
Find the Decision Makers at Your Target Accounts by Job Title
Turn a list of company domains into a CRM-ready CSV of people by job title, with LinkedIn URLs, labeled emails and a company check on every row.
B2B Leads Finder: Business Emails and LinkedIn Profiles Without Apollo or ZoomInfo
Find business emails, LinkedIn profiles, and job titles for decision-makers at target companies. No Apollo, ZoomInfo, or Lusha API key required. $0.003 per lead.
Track Daily Rank Changes in an Amazon Best Sellers Category
Run Amazon Bestsellers Scraper every morning, diff each ASIN's rank against yesterday, and flag new entrants, drop outs and big movers in Python.
How to Scrape LinkedIn Employees Without Login or Sales Navigator
LinkedIn has no public API for employee data. Learn how to pull B2B leads, employee lists, and org chart data from LinkedIn company pages without a LinkedIn account or Sales Navigator subscription.