To build a B2B lead list, run five steps in order: define your ICP criteria, choose a data source, enrich each record with contact details, verify the emails, and organize everything under one clean schema. Done right, the output is a deduplicated, personalization-ready sheet or CRM segment you can hand straight to outreach.
Most lead lists fail for boring reasons: no clear definition of a good fit, stale data, unverified emails, and a spreadsheet where every row has slightly different columns. This playbook fixes all four with a repeatable process and two concrete schemas you can copy today.
Step 1: Define Your Criteria (Write the ICP Down)
An Ideal Customer Profile (ICP) is the filter every prospect must pass. For local and SMB B2B, a workable ICP has these dimensions:
- Geography: the cities or radius you serve.
- Category: the business types you sell to.
- Size signal: a proxy you can actually observe - review count, headcount range, number of locations.
- Quality signal: rating floor, "has a website", "operational" status.
- Exclusions: franchises, competitors, existing customers, anyone already in your CRM.
Write it as a single sentence you could hand to a stranger: "Operational independent dental practices within 25 km of Birmingham, with a website and 20+ Google reviews, excluding chains." That sentence becomes your source query and your QA checklist.
Step 2: Source the Businesses
Now turn the ICP into a list of real businesses. You have the three options covered in how to find businesses to contact: manual Google Maps research, a bought directory list, or a business data API. For anything you plan to rebuild regularly, an API wins because the query IS your ICP.
If you are still choosing that source, the business data API guide and the Google Places API vs scrapers comparison cover the trade-offs. With biz collect, the sourcing step is one request that mirrors the ICP sentence:
{
"location": "Birmingham, UK",
"keywords": ["dental practice", "dentist"],
"radius_km": 25,
"scrape_emails": true,
"coverage": "exhaustive"
}
coverage: "exhaustive" tiles the radius into a grid to beat Google's 60-results-per-query ceiling, so you approach full coverage of the area instead of the first 60 hits. You get back a businesses array where each record already carries name, address, phone, website, rating, review count, category, hours, and (because scrape_emails is true) emails pulled from each business's own site.
Step 3: Enrich With Contact Details
Discovery gives you the business; enrichment gives you the human path in. This is where map data alone falls short - Google Places returns no emails, so the address has to come from each business's website.
biz collect does this enrichment inside the same job. For every business it visits the site and returns:
- emails - deduped, ranked best-contact-first (on-domain mailboxes above free-provider, above off-domain).
- email_details - per address: a
confidencetier, whether the domain has MX records, anis_role_accountflag, and a resolved contact (the named person, their title, and a salutation) when the site names one. - people - the full roster of named people the site published (Impressum / team / about pages), even ones not tied to a scraped email.
That contact object is what lets you write "Hi Dr. Weber" instead of "Hi there" - the difference between a real B2B touch and spray-and-pray. If you would rather enrich a list you already own from raw websites, the extract emails from any website guide covers that path.
Step 4: Verify Before You Send
Sending to unverified addresses burns your domain reputation and inflates bounce rates. Verification has two layers:
- Syntax + MX (free, automatic in good sources). Is the address well-formed, and does its domain actually accept mail? biz collect does this on every scraped email and exposes it as the
confidencetier andhas_mxflag - no extra step or cost. - Mailbox-level checks (optional, third-party). Dedicated verification tools attempt deeper checks. Note the honest limit: no responsible tool guarantees a live mailbox without risky SMTP probing, so treat "high confidence" as "very likely deliverable", not "guaranteed".
A practical rule: send to high confidence first, hold low/unknown for a warm-up or a manual look, and drop role/no-reply addresses from personalized sequences.
Step 5: Organize Under One Schema
The final step is what separates a lead list from a lead mess: every row shares the same columns, IDs are stable, and duplicates are gone. Here is a lead-list schema you can adopt directly.
Lead list schema (one row per business)
| Column | Type | Source | Notes |
|---|---|---|---|
lead_id | string | your system | Stable primary key; dedupe on this. |
business_name | string | name | |
website | url | website | Dedupe key candidate (normalize host). |
primary_email | emails[0] | Best contact, on-domain first. | |
email_confidence | enum | email_details[0].confidence | high / medium / low / unknown. |
contact_name | string | email_details[0].contact.full_name | Empty for role inboxes. |
contact_title | string | email_details[0].contact.title | For personalization. |
phone | string | phone | Fallback channel. |
city | string | derived from resolved_location | For segmenting. |
category | string | primary_type | Segment key. |
rating | number | rating | Quality signal. |
review_count | int | user_rating_count | Size proxy. |
status | enum | your system | new / queued / contacted / replied / won / lost. |
sourced_at | date | job completed_at | Freshness stamp; re-source after N days. |
Dedupe rules (apply in order)
- Exact
websitehost match (stripwww., lowercase). - Exact normalized
business_name+citymatch. - Same
primary_emailacross two rows.
Keep the row with the higher email_confidence; merge phone/social from the discarded one.
Because biz collect returns stable JSON and a CSV/XLSX export with fixed columns, mapping into this schema is a straight field-to-column copy - no HTML parsing, no per-source cleanup. Teams that want this to run on a schedule can wire it into n8n, Make, or an AI agent pipeline.
A Worked Example
Say you want dental practices around Birmingham. You run the Step 2 request, get 84 businesses back, of which 61 have a website and 47 yield at least one high or medium confidence email. After deduping on website host you are at 44 unique leads. You map them into the schema above, tag the 31 with a resolved contact_name as "personalize", and route the 13 role-only inboxes to a lighter, non-personalized touch. That is a clean, send-ready B2B lead list built in one afternoon - and rebuildable next quarter by re-running one request.
The Bottom Line
A B2B lead list is a small data product: defined by an ICP, sourced fresh, enriched with real contacts, verified for deliverability, and organized under one schema with dedupe rules. Nail the schema and the process, and every future campaign starts from a clean, repeatable base instead of a blank spreadsheet.
Frequently asked questions
- What makes a good B2B lead list?
- A clear ICP, fresh source data, verified deliverable emails, and a single consistent schema with stable IDs and dedupe rules. A list that is merely large but stale, unverified, and inconsistently structured produces bounces, duplicate outreach, and low reply rates.
- How do I build a B2B lead list from scratch?
- Follow five steps: (1) write your ICP criteria, (2) source matching businesses (manual, a directory, or a business data API), (3) enrich each with contact details from the business website, (4) verify emails for deliverability, and (5) organize everything under one schema with dedupe rules before importing to your CRM.
- How should I structure a lead list spreadsheet?
- Use one row per business with fixed columns: a stable lead_id, business name, website, primary email, email confidence, contact name and title, phone, city, category, rating, review count, a status field, and a sourced_at date. Dedupe on website host first, then name+city, then email.
- How often should I rebuild a B2B lead list?
- It depends on churn in your target market, but a common cadence is every 60 to 90 days, because businesses close, move, and rebrand continuously. This is why a re-runnable source (a business data API you can query on demand) beats a one-time bought list you cannot refresh.
- Do I need a separate email verification tool?
- Not always. A good source verifies syntax and MX records automatically and scores each address, which covers most of the risk. A dedicated verification tool adds deeper checks for high-stakes sends, but be aware that no tool can guarantee a live mailbox without risky probing, so treat confidence tiers as probabilities, not certainties.





