Home / Stage 3 of 6
๐Ÿ‘ค Stage 3

Find Your Contacts

Outreach isn't sent to companies โ€” it's sent to people. Stage 3 finds the specific human at each company who can say yes.

What is this?

Contact finding means connecting each company to a real person โ€” name, title, email address, and LinkedIn profile. You're looking for the decision-maker: the founder, owner, or executive director who can actually say yes to a proposal.

Where do contacts come from?

Three sources, tried in order:

  1. The company website โ€” Many agencies list their team. The About or Team page is the best source because it often includes photos, roles, and sometimes emails.
  2. LinkedIn search โ€” Search for people at the company with the right title. LinkedIn is the most complete professional directory in the world.
  3. Email pattern guessing โ€” If you know a name and a domain, a script can try the most common email patterns (firstname@domain.com, first.last@domain.com) and verify which one exists.

What does a good contact record look like?

Name: Sarah Chen
Title: Founder & Creative Director
Company: PixelCraft Studio
Email: sarah@pixelcraft.com โœ“ verified
LinkedIn: linkedin.com/in/sarahchen
Source: company website (About page)
60โ€“70%
of companies yield a usable contact
3
sources tried per company
EP0โ€“EP3
progressive enrichment pipeline stages
Contact finding is the most complex stage because it combines web scraping, LinkedIn data, and email verification โ€” three different systems that each fail in different ways. The key is to run them in order and stop as soon as you have a verified contact.
1

EP0 โ€” Validate the domain first

Before spending any time on a company, confirm its website actually loads and the domain is real. Dead companies, parked domains, and agencies that have gone out of business are filtered out here. Saves wasted calls downstream.

2

EP1 โ€” Scrape the company website

Search for contact information on the company site: team pages (/about, /team, /staff), contact pages, footers. Use AI to extract names, titles, and any email addresses visible on the page. Small agencies often list their founder directly.

3

EP2 โ€” Search LinkedIn for the person

Use search to find the decision-maker at the company by name and title. This step finds the LinkedIn profile URL, which is used later for connection requests. You don't need LinkedIn automation here โ€” a search query is enough to locate the profile.

3

EP3 โ€” Find and verify the email

Given a name and domain, try the most common email patterns. Then send a verification ping to see which address actually exists. The most common patterns: firstname@domain.com, first.last@domain.com, firstlast@domain.com. A verified email is the most valuable asset in your database.

5

Score each contact

Not all contacts are equal. Score based on: is the email verified? Is there a LinkedIn URL? Is the title a decision-maker title? Does company size fit? High scores become your LinkedIn funnel. Medium scores become email-only. Low scores get deprioritized.

Audit your failures. When a contact can't be found, log why. After 500 failures, patterns emerge โ€” maybe team pages use a different URL path, or agencies in a certain city all use a specific email format. Those insights feed the next iteration of your scraper.
Serper API (search) Jina Reader Claude Haiku SMTP verify Unipile API (LinkedIn) SQLite

Accounts & costs

Service What it does Cost
Serper API Google search results to find team pages & LinkedIn profiles $0.001 per query (~$3 per 3,000 searches)
Jina Reader Fetches team/about pages as clean text Free for low volume
Claude Haiku Extracts names and titles from page text ~$5โ€“10 for 29k companies
Unipile API LinkedIn profile lookup + connection sending ~$99/mo
Claude Code Prompt โ€” Build the contact finder
I have a SQLite database with an "agencies" table. I want to find the founder/owner contact at each agency. Build a multi-stage enrichment pipeline: Stage EP0 โ€” Validate: Check the domain resolves. Mark dead domains as status='dead'. Stage EP1 โ€” Website scrape: For each valid agency: 1. Use Serper to search: "site:{domain} founder OR owner OR about OR team" 2. Fetch the top result URL with Jina Reader 3. Send to Claude Haiku with prompt: "Extract the founder or owner's full name, title, and email if visible. Return JSON: {name, title, email, confidence}" 4. Store results in a "contacts" table linked to agency_id Stage EP3 โ€” Email patterns: For contacts with a name but no email: 1. Try patterns: {first}@{domain}, {first}.{last}@{domain}, {first}{last}@{domain} 2. Verify each via SMTP (connect to the domain's mail server, check if address accepts) 3. Store the verified email Add a contacts_status column: 'found', 'not_found', 'dead', 'low_confidence' Log all failures with reason in an enrichment_log table.
Claude Code Prompt โ€” Add LinkedIn profile finder
For contacts where we have a name and company but no LinkedIn URL, add a LinkedIn lookup step: 1. Use Serper to search: '"{first} {last}" "{company_name}" site:linkedin.com' 2. Parse the first result URL โ€” if it matches linkedin.com/in/*, extract the profile slug 3. Store as linkedin_url in the contacts table 4. Set li_found = 1 if successful Don't use the LinkedIn API directly โ€” just find the public profile URL via Google. This URL will be used later when we send connection requests via Unipile. Run this as EP2, after EP1 (website scrape) and before EP3 (email verification). Skip contacts that already have li_found = 1.

The enrichment pipeline (EP funnel)

Each stage adds information and some contacts fall off. That's expected. Here's what a realistic funnel looks like for 10,000 starting domains:

EP0 Valid domains: 9,200
EP1 Contact found on site: 5,800
EP2 LinkedIn URL: 4,400
EP3 Email verified: 3,200

3,200 verified contacts out of 10,000 starting domains is an excellent result โ€” typical enrichment pipelines hit 25โ€“35% at the verified-email stage.

Outreach Machine Playbook ยท Built with Claude Code ยท Back to overview