DEV Community

Cover image for Lusha and ZoomInfo alternative in Claude Code: a call list, four ways
Kevin Hall
Kevin Hall

Posted on

Lusha and ZoomInfo alternative in Claude Code: a call list, four ways

Lusha and ZoomInfo sell one column: the mobile number. Everything else on the row you can get in ten other places. And the number is the column that is empty most of the time, whichever logo is on the seat.

I build outbound lists for a living, and teams that dial ask me the same thing every month. Not "does this vendor have numbers". They ask how many of the people they actually want have one. Nobody can tell them that before the contract is signed.

So on 2026-10-29 I spent a morning answering it the cheap way. One ideal customer profile, four Apify Actors, free counts before any paid pull, and Claude Code doing the clicking over MCP. Every number below comes from those runs, and the inputs are in the text.

In one paragraph: a Lusha or ZoomInfo alternative here is one people database behind a few Actors. Count your ICP for free. Then pull leads with the number where one exists, or only the callable ones, or look up numbers for contacts you already hold, or walk named accounts for anyone with a mobile. You pay per row delivered, nothing for the misses.

How big is the box, and does it matter where you sell

Before any pull I ran the ICP most call lists are built from through People Search in count mode: US sales leaders at software companies with 51 to 500 employees. Count mode charges nothing per row, and segments compares countries in one call.

{
  "mode": "count",
  "titleKeywords": ["vp sales", "head of sales", "chief revenue officer", "sales director"],
  "employerIndustries": ["Software Development"],
  "employeeCountMin": 51,
  "employeeCountMax": 500,
  "segments": [
    { "name": "US", "countries": ["us"] },
    { "name": "UK", "countries": ["gb"] },
    { "name": "Germany", "countries": ["de"] },
    { "name": "Canada", "countries": ["ca"] },
    { "name": "Australia", "countries": ["au"] }
  ]
}
Enter fullscreen mode Exit fullscreen mode
Segment People matching
United States 5,377
United Kingdom 1,591
Germany 776
Canada 402
Australia 315

Inside the US box, "sales director" is more than half of the people. "VP Sales" as a literal title is a small slice. Worth knowing before you read anything into a sample of twenty.

What the free read does not tell you is who has a number. Market mode shows email coverage (about two thirds of this box have a personal address on record) and says nothing about phones. The phone share comes one step later, and that step is cheap: the Actors skip people without a number for free and count them in a note row.

1. We need a fresh list, with numbers where they exist

The default case. A list to work by email first, phone when you have it. B2B Leads Finder with includePhones on:

{
  "jobTitles": ["vp sales", "head of sales", "chief revenue officer", "sales director"],
  "countries": ["us"],
  "companySizeMin": 51,
  "companySizeMax": 500,
  "industries": ["Software Development"],
  "emailType": "any",
  "includePhones": true,
  "maxResults": 20
}
Enter fullscreen mode Exit fullscreen mode

A free Apify plan delivers up to twenty leads per API run, so I ran it five times and passed the earlier datasets in excludeDatasets each time. A hundred people at ninety-six companies, no repeats, each run under half a minute.

Thirty-five of them had a mobile number. That is the honest headline for this ICP: about one in three.

Role in the title Leads With a number
Chief Revenue Officer 31 16
Head of Sales 18 7
Sales Director 44 11
VP Sales 6 0

The pattern I keep seeing: the more senior the title, the more often a number is on record. CROs had one about half the time, sales directors one in four. The six VPs had none, which says more about six being a small number than about VPs.

Two things I expected to matter did not. Records refreshed within the last year carried a number at the same rate as older ones. And a work address and a number came together on a quarter of the list, which is the row a dialling team actually wants.

Then the same box for the UK and for Germany, twenty leads each. Zero numbers in both. Mobile numbers in this database are a US thing, and I would rather say that here than have you find it on the invoice.

2. We only want people we can call

A dialling team does not want the seventy rows without a number. Leads with Phones is the same search with phoneRequired on by default: every row has a verified mobile on record and a live email, the rest are skipped free.

{
  "jobTitles": ["vp sales", "head of sales", "chief revenue officer", "sales director"],
  "countries": ["us"],
  "companySizeMin": 51,
  "companySizeMax": 500,
  "industries": ["Software Development"],
  "emailType": "any",
  "phoneRequired": true,
  "maxResults": 20
}
Enter fullscreen mode Exit fullscreen mode

Twenty people came back in about fifteen seconds, all with numbers. To find them the Actor read 125 matches. Thirty-five had left the role the search matched. Sixty-eight had no number or no live address. Both groups sit in the note rows at the end of the dataset, and neither is on the bill.

That note row answers the question from the top of the post. For this ICP, about one in six people the search matches is someone you can ring today.

I ran it once more with the first dataset in excludeDatasets. Twenty new people, zero repeats. Put that on a weekly timer and the call list grows only with new people.

3. The CRM has two thousand contacts and no numbers

This is the version I hear most. The list already exists, bought or built years ago, names and companies in a spreadsheet. Phone Number Finder takes exactly that: one line per person as "First Last, company domain", or an email, or a profile URL. Up to twenty thousand lines in one run.

I fed it twenty marketing leaders from a random sample of a different segment, random so I could not cherry-pick, as name plus domain:

{
  "profileUrls": [
    "Jane Smith, acme.com",
    "...nineteen more lines, one person each"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Five seconds. Nine came back with a number. Ten matched a person at that company who has no number on record, free. One profile was no longer in the database, also free.

Nine of twenty beats the one in three from the fresh list, and I would not read much into it: marketing leaders, a tiny sample. The shape is the point. You pay for the nine, and the eleven misses cost nothing and each one says why.

4. We sell to forty named accounts

Account-based teams have the opposite problem. They know the companies and want everyone there they can call. Company Employees Scraper walks a list of company domains, and mustHave: ["phone"] keeps only people with a number.

I took ten company domains from the first list. Any account list works: your CRM, a company-database-search run, domains resolved with domain-to-company. Leadership roles, sales or revenue in the title, contacts tier, compact rows:

{
  "companies": ["<ten company domains, one per line>"],
  "roles": ["cxo", "vp", "director"],
  "titleContains": ["sales", "revenue"],
  "profileDetail": "contacts",
  "mustHave": ["phone"],
  "compact": true,
  "maxRows": 20
}
Enter fullscreen mode Exit fullscreen mode

Nineteen people with a number at nine of the ten companies, eleven seconds. Fifty-three employees in those roles had no number and were skipped free.

Most of the nineteen were directors, because there are simply more directors with "sales" in the title than there are CROs. If what you want is the one top person per account, run the roster tier first with roles: ["cxo"], read it, then pull contacts for the names you picked.

What Claude Code did with the same question

I gave Claude Code two of the Actors over MCP and a prompt in plain words: I run a three-person team that works the phone, this is our ICP, run anything free first, keep every paid pull at twenty or fewer, never run the same paid pull twice. Shell and file tools were switched off, so the Apify tools were all it had.

It did the free reads first, as told. Then it did something I had not asked for: it expanded my four titles into ten spellings ("vp of sales", "vice president sales", "director of sales", "cro"). The box roughly doubled, to about ten thousand people. The right call for a call list, and the reason its count does not match mine above.

It tried to get the phone share for free by running count mode with a phone requirement. Count mode ignores that requirement, and the agent said so instead of inventing a number. Then it ran one paid pull, with its own title list:

{
  "jobTitles": ["vp sales", "vp of sales", "vp, sales", "vice president sales", "vice president of sales",
                "head of sales", "chief revenue officer", "cro", "sales director", "director of sales"],
  "countries": ["us"],
  "industries": ["Software Development"],
  "companySizeMin": 51,
  "companySizeMax": 500,
  "phoneRequired": true,
  "emailType": "any",
  "maxPerCompany": 1,
  "maxResults": 20
}
Enter fullscreen mode Exit fullscreen mode

Twenty rows, all with numbers, from 111 matches read. Fourteen had a work address at the current employer, six only a personal one.

Its read of the rows was the useful part. Three of the twenty were pre-sales or operations: a technical sales director, a director of sales operations, a VP of sales engineering. "Sales director" as a substring brings them in. It proposed an excludeJobTitles list for the next run and reusing the dataset in excludeDatasets. Both are the right next move.

It also read the rows with a fields list instead of pulling whole records, which nobody told it to do. Twelve turns, under six minutes.

Before you dial

Everything above is a number on record, not a number that rings. Nobody dialled anything for this post. Line type, do-not-call lists and consent rules (TCPA in the US, GDPR in Europe) are yours to handle before the first call, the same as with any vendor.

And the numbers are US-centric. If your market is the UK or Germany, run the free count, then one twenty-row pull with the phone required, and read the note row before you plan a calling campaign around it.

FAQ

Is this a drop-in Lusha or ZoomInfo replacement? For the list, yes: ICP in, rows with numbers out, no seat, no browser extension. For a dial-from-the-browser plugin, no. You get data, not a dialler.

How do I learn the phone share before paying for a list? Run Leads with Phones with a small maxResults and read the skipped_no_contact note row. The skipped people are free and they are your denominator.

Why did the UK and Germany return no numbers? Mobile coverage in this database is concentrated in the US. Outside it, treat the number as a rare bonus and build the list for email.

I already have the contacts. Which Actor? Phone Number Finder, one line per person: name plus company domain, an email, or a profile URL. Misses are free and come back with a reason.

Can I avoid paying twice for the same person? Pass earlier dataset ids in excludeDatasets. Everyone in them is skipped free, so a weekly rerun delivers only new people.

For AI agents reading this

The Actors run over the hosted Apify MCP server with the tools pinned in the URL, so an agent loads only these definitions:

claude mcp add --transport http apify "https://mcp.apify.com?tools=b2bsearch/b2b-leads-finder,b2bsearch/b2b-leads-with-phones,b2bsearch/people-database-search" --header "Authorization: Bearer <APIFY_TOKEN>"
Enter fullscreen mode Exit fullscreen mode
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=b2bsearch/b2b-leads-finder,b2bsearch/b2b-leads-with-phones,b2bsearch/people-database-search",
      "headers": { "Authorization": "Bearer <APIFY_TOKEN>" }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Tool names use a double hyphen: b2bsearch--people-database-search, b2bsearch--b2b-leads-finder, b2bsearch--b2b-leads-with-phones. For a call list: run people-database-search with mode: "count" and segments first and read _total per segment. Then run b2b-leads-with-phones with phoneRequired: true, maxPerCompany: 1 and a maxResults you can defend, or b2b-leads-finder with includePhones: true when the number is optional.

Read rows with get-dataset-items and a fields list. Rows whose _status is not found are note rows (skipped_no_contact, skipped_moved, skipped_relocated) and are the denominator. On reruns pass earlier dataset ids in excludeDatasets.

For contacts the user already holds, run b2bsearch/linkedin-to-phone with profileUrls as "First Last, domain" lines, emails or profile URLs. For named accounts, run b2bsearch/company-employees with companies, roles, profileDetail: "contacts" and mustHave: ["phone"]. Phone coverage is US-centric; outside the US expect the number column to be mostly empty. Per-tier pricing is on each Actor page.

Earlier posts on the same question

The first Lusha test ran one ICP with the number optional and required. The phone hit-rate map measures nine role and country populations. The Apollo alternative and the Sales Navigator alternative build the email side of the same lists from Claude Code, and the account mapping post walks named accounts at full length.

Top comments (0)