Pulling Emails and Phones From a Site
Outcome: a contact-recovery column that runs only on rows enrichment missed, with role addresses filtered out and everything verified before use.
- Surface
- Sync GTM app and MCP server
- Level
- Beginner
- Uses
- scrape_emails_from_website · scrape_phones_from_website · verify_email
- Credits
- ~6 for 20 rows
- Prerequisite
- A run of contact enrichment with some misses
When this is the right tool
Contact databases cover corporate B2B well and everything else patchily. Site scraping fills three specific gaps:
- Small and local businesses — no LinkedIn presence, but a phone number on every page
- Non-English markets — thinner database coverage, same public website
- The tail of any list — the 25% your waterfall missed
It is a fallback, not a first choice. Run it on rows where enrichment returned nothing, not on the whole table.
Reference: scrape_emails_from_website, scrape_phones_from_website.
Where contact details live
| Page | What you find |
|---|---|
/contact | The main address and phone, usually a shared inbox |
| Footer of any page | Often the most reliable single place |
/about or /team | Individual addresses at smaller companies |
/support or /help | Support addresses — usually the wrong target |
| Legal or imprint pages | Required disclosures in some markets, and highly reliable where required |
The scraper reads the site rather than one path, so you usually do not have to choose. What you do have to do is filter what comes back.
Filtering what you get
A raw scrape returns every address on the site. Most are not useful and some are actively harmful to send to.
Drop the never-send addresses
abuse@, privacy@, legal@, dmca@, postmaster@, noreply@. Mailing these is a complaint waiting to happen.
Separate role addresses from personal ones
info@, hello@, contact@, sales@ are role addresses. Useful in some segments, useless in others — see below.
Drop third-party domains
Addresses whose domain does not match the company. These usually belong to the agency that built the site.
Keep personal addresses
firstname.lastname@company.com — the actual prize, and common on smaller sites.
A simple pattern rule handles most of this as a free formula column.
Is a shared inbox worth it?
Depends entirely on the segment.
| Segment | Verdict |
|---|---|
| Local business, trades, clinics, restaurants | Yes. The owner reads it. Often the only route in. |
| Small agencies and consultancies, under ~20 people | Usually. Read by someone with authority. |
| Mid-market B2B | Rarely. Routed to support or ignored. |
| Enterprise | No. Goes nowhere. |
And the message must change with the target. A shared inbox is read by someone busy who did not ask to hear from you — short, concrete, and specific to their business, or it is deleted in two seconds.
Verify anyway
Scraped addresses are unverified by definition, and they bounce more than enriched ones — sites carry addresses that were retired years ago.
Run verify_email over every scraped address before it enters any sequence. It is cheap, and it is the difference between recovering the tail of your list and damaging your sending domain to reach it.
Do this now
Filter to the misses
Rows where contact enrichment returned nothing. This is the only input set.
Confirm you have a website
No site means nothing to scrape. Those rows need a different path — phone, LinkedIn, or nothing.
Scrape emails on five rows
Read everything returned, including the addresses you would never send to.
Build the filter
A formula column implementing the four rules above.
Scrape phones on the same rows
Compare against any number you already have. Direct lines beat switchboards.
Verify every email
Then keep only valid.
Measure recovery
What percentage of previously-missing rows now have a contactable path? That number tells you whether this column is worth keeping.
Check your work
- The column ran only on rows enrichment missed
- Never-send and third-party addresses are filtered out
- Role addresses are distinguishable from personal ones
- Every scraped address has been verified
- You have a recovery rate figure
Where this breaks
Sending to every address a scrape returns is how a sender reputation gets destroyed in one campaign. Spam-trap and abuse addresses exist on plenty of sites specifically to catch this behaviour, and hitting one has consequences that outlast the campaign by months. The filter is not a tidiness step — it is the point of the lesson.
Further automation
Chain it: enrich → check for a miss → scrape site → verify → merge into one best_contact column with a contact_source field next to it. The source field is what lets you compare reply rates between enriched and scraped contacts later, and that comparison usually justifies or kills the column.
Next lesson
05 — Research agents, moving from “read this page” to “go find out”.
Reference for this lesson: scrape_emails_from_website, scrape_phones_from_website, Verify email, Waterfall Enrichment.