How to Scrape Emails From Multiple Websites
Scraping email addresses from multiple websites involves building a process that can visit a list of permitted websites, locate relevant pages, identify publicly displayed email addresses, clean the results, remove duplicates, and save everything in a structured database or spreadsheet.
Doing this across multiple domains is considerably more complicated than scraping one website. The main challenges are URL management, crawling, different website structures, rate control, JavaScript-rendered content, data cleaning, deduplication, and maintaining a reliable record of where every address came from. At larger scale, concurrency and bookkeeping become major parts of the problem.
This guide focuses on legitimate research and business use of publicly available information from websites you are permitted to crawl.
What Does Scraping Emails From Multiple Websites Mean?
Instead of processing one website:
Website A
↓
Find emails
you process a list:
Website A ──┐
Website B ──┤
Website C ──┤
Website D ──┤──→ Email Extraction
Website E ──┤
Website F ──┘
For example, your input file might contain:
company-a.com
company-b.com
company-c.com
company-d.com
company-e.com
The scraper processes each domain independently and produces something like:
| Website | Type | Source Page | |
|---|---|---|---|
| company-a.com | info@company-a.com | General | /contact |
| company-a.com | sales@company-a.com | Sales | /sales |
| company-b.com | hello@company-b.com | General | / |
| company-c.com | press@company-c.com | Press | /press |
Why Multiple-Website Scraping Is More Difficult
Scraping 10 websites manually is relatively straightforward.
Scraping 10,000 websites creates several new problems.
1. Different website structures
One website may use:
/contact
another:
/contact-us
another:
get-in-touch
and another may have no dedicated contact page.
2. Different technologies
You may encounter:
- Static HTML
- WordPress
- React
- Vue
- Angular
- JavaScript applications
- Server-rendered websites
- Embedded forms
- PDFs
- Dynamically loaded content
A basic HTTP scraper may not see content generated after JavaScript executes.
3. Different access rules
Every domain can have different:
robots.txtrules- Terms of service
- Rate limits
- Crawl restrictions
- Server configurations
A multi-domain crawler should therefore treat each website separately rather than assuming one global policy applies to every domain
The Basic Multi-Website Workflow
A reliable process looks like this:
Website List
↓
Validate URLs
↓
Check Website Rules
↓
Create Crawl Queue
↓
Visit Homepage
↓
Discover Relevant Pages
↓
Extract Emails
↓
Clean Results
↓
Deduplicate
↓
Verify
↓
Store Source Information
↓
Export
For larger projects:
URL Database
↓
Crawl Queue
↓
Multiple Workers
↓
Domain-Level Rate Limiting
↓
HTML / Browser Extraction
↓
Email Parser
↓
Data Cleaning
↓
Database
Step 1: Prepare Your Website List
Start with a CSV or spreadsheet.
Example:
| ID | Company | Website |
|---|---|---|
| 1 | Company A | company-a.com |
| 2 | Company B | company-b.com |
| 3 | Company C | company-c.com |
| 4 | Company D | company-d.com |
You can also store:
- Country
- Industry
- Category
- Priority
- Date added
- Processing status
A larger file might look like:
id
company
domain
industry
country
priority
status
Step 2: Normalize Website URLs
Users may provide websites in different formats:
company.com
www.company.com
https://company.com
https://www.company.com/
Your system should normalize these into a consistent representation.
For example:
https://company.com
This makes it easier to:
- Identify duplicates
- Group pages by domain
- Track crawling
- Store results
Step 3: Remove Duplicate Domains
Your input might contain:
company.com
www.company.com
https://company.com
https://company.com/
These are likely the same website.
Normalize first and then deduplicate.
Step 4: Check the Website’s Crawling Rules
Before beginning the crawl, check:
https://example.com/robots.txt
robots.txt communicates instructions to automated crawlers about which areas should or shouldn’t be crawled. It is important to follow applicable instructions and also review the site’s terms
For a large project, store the result:
Domain
robots_checked
crawl_allowed
checked_at
For example:
| Domain | Robots Checked | Status |
|---|---|---|
| company-a.com | Yes | Allowed |
| company-b.com | Yes | Restricted |
| company-c.com | Yes | Allowed |
Step 5: Check Terms and Conditions
robots.txt isn’t the only consideration.
A website’s terms may contain restrictions concerning:
- Automated access
- Data extraction
- Commercial use
- Reproduction
- Database creation
For business projects, review the applicable rules before scaling up. Current scraping guidance consistently recommends checking both robots.txt and terms of service
Step 6: Check for an API First
Before scraping HTML, check whether the information is available through:
- Official API
- Public dataset
- Partner feed
- Export function
An API can be more stable and structured than HTML scraping and may reduce the amount of crawling necessary.
Step 7: Start With a Small Test
Don’t immediately submit 100,000 websites.
Start with:
10 websites
Then:
50 websites
Then:
100 websites
Measure:
- Emails found
- Websites successfully processed
- Errors
- Duplicates
- Processing time
- False positives
- Pages crawled
Only scale after the workflow works correctly.
Step 8: Visit the Homepage
For each website:
Company A
↓
Homepage
Extract:
- Visible text
- Links
mailto:links- Relevant metadata where appropriate
The homepage often contains an email in the footer or contact section.
Step 9: Discover Relevant Internal Pages
The homepage should be treated as the starting point, not the entire website.
Look for links containing words such as:
contact
contact-us
about
about-us
team
staff
leadership
company
support
sales
press
media
careers
For example:
Homepage
├── About
├── Services
├── Team
├── Contact
├── Press
└── Careers
Prioritizing contact-bearing pages is generally more efficient than blindly crawling every page.)
Step 10: Set a Crawl Depth
You don’t want your scraper to follow every link forever.
For example:
Depth 0
Homepage
Depth 1
Contact
About
Team
Depth 2
Individual team profiles
A practical system might use:
Maximum depth: 2
Maximum pages/domain: 20–50
The appropriate limits depend on the project.
Step 11: Extract mailto: Addresses
A website might contain:
<a href="mailto:sales@example.com">
Sales
</a>
Your scraper can identify:
mailto:
and extract:
sales@example.com
This is generally more reliable than searching only visible text.
Step 12: Extract Email Patterns From Text
You can also search webpage text for patterns resembling:
name@example.com
A common pattern is:
[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}
It can identify examples such as:
info@example.com
sales@example.co.uk
john.smith@example.org
However, regex should not be considered an email verification system.
Step 13: Search the Page Source Carefully
Some websites may contain an address in:
- HTML attributes
mailto:links- Embedded structured content
- Metadata
- JavaScript variables
However, blindly searching every script can produce irrelevant matches.
A better approach is:
Visible content
+
mailto links
+
relevant HTML attributes
before expanding into more complicated extraction.
Step 14: Handle Obfuscated Emails
Some websites intentionally format addresses like:
john [at] example [dot] com
or:
john(at)example(dot)com
or:
john at example dot com
A normalization stage can recognize common forms.
For example:
john [at] example [dot] com
can become:
john@example.com
But normalization should be conservative to avoid turning ordinary webpage text into false email addresses.
Step 15: Handle JavaScript Websites
Some websites don’t contain all visible content in the initial HTML.
Instead:
Initial HTML
↓
JavaScript
↓
Content loads
↓
Rendered page
A basic requests scraper may therefore miss information.
For these websites, authorized crawling may require a browser automation tool capable of rendering JavaScript.
Examples include:
- Playwright
- Puppeteer
- Selenium
The general architecture becomes:
URL
↓
Browser
↓
JavaScript executes
↓
Rendered DOM
↓
Email extraction
Browser rendering should be used for sites you are permitted to crawl, not as a means of circumventing access restrictions.
Step 16: Don’t Assume Every Website Has an Email
This is one of the most important lessons.
Some websites have:
Email
Others have:
Contact form
Others:
Phone
Others:
Social media
And some provide no obvious contact channel.
Your database should therefore support:
email_found
email_not_found
contact_form
phone_only
restricted
error
Step 17: Store the Source URL
Never store only:
sales@example.com
Prefer:
Email:
sales@example.com
Website:
example.com
Source:
https://example.com/contact
Collected:
2026-08-25
This makes the dataset auditable.
Step 18: Store the Website Domain
Every email should remain associated with its domain.
Example:
| Domain | |
|---|---|
| info@abc.com | abc.com |
| sales@abc.com | abc.com |
| contact@xyz.com | xyz.com |
This makes later filtering much easier.
Step 19: Classify Emails
Not all addresses serve the same purpose.
General
info@
hello@
contact@
Sales
sales@
sales-team@
Support
support@
help@
customer-service@
Media
press@
media@
communications@
Careers
careers@
jobs@
recruitment@
Individual
john.smith@
mary.jones@
Classification makes the dataset considerably more useful.
Step 20: Separate Generic From Individual Addresses
Consider:
info@example.com
versus:
john.smith@example.com
The first is a general business contact.
The second may identify an individual and therefore may require additional privacy considerations depending on how you process and use it.
For that reason, don’t automatically treat every extracted address as equivalent.
Step 21: Normalize Emails
You might receive:
INFO@EXAMPLE.COM
info@example.com
info@example.com
Normalize them to:
info@example.com
Typical cleaning includes:
- Removing whitespace
- Removing surrounding punctuation
- Standardizing case
- Decoding HTML entities
- Normalizing obvious obfuscation
- Removing duplicates
Step 22: Deduplicate Within Each Website
Suppose:
Homepage → info@example.com
Contact → info@example.com
About → info@example.com
Footer → info@example.com
The result should be:
info@example.com
rather than four records.
Step 23: Deduplicate Across Websites
You may also discover the same email on different websites.
For example:
info@example.com
info@example.com
A global deduplication stage can remove duplicates.
However, don’t automatically delete different addresses belonging to the same domain:
sales@example.com
support@example.com
info@example.com
These are different contacts and may all be useful.
Step 24: Validate the Data
Email extraction is not the same as verification.
An extracted address might be:
- Incorrect
- Old
- Abandoned
- Typographically malformed
- A placeholder
- A generic mailbox
- A catch-all address
A validation process can examine:
Syntax
↓
Domain
↓
DNS/MX
↓
Other deliverability signals
The exact level of verification depends on the purpose of the project.
Step 25: Never Treat Guessed Emails as Scraped Emails
Suppose the website says:
John Smith
but doesn’t publish his email.
You shouldn’t automatically generate:
john.smith@example.com
and put it into the database as though you extracted it.
Maintain separate fields such as:
observed_email
inferred_email
if your project legitimately needs both.
Step 26: Build a Multi-Website CSV
A useful output could be:
company,domain,email,type,source_url,status
ABC Ltd,abc.com,info@abc.com,general,https://abc.com/contact,found
ABC Ltd,abc.com,sales@abc.com,sales,https://abc.com/contact,found
XYZ Ltd,xyz.com,hello@xyz.com,general,https://xyz.com,found
Example Ltd,example.com,,,https://example.com/contact,not_found
This is far better than a simple text file containing thousands of addresses.
Step 27: Create a Processing Status
For thousands of websites, track each domain.
For example:
pending
processing
completed
no_email
restricted
error
retry
Your system might look like:
| Domain | Status | Emails |
|---|---|---|
| abc.com | Completed | 3 |
| xyz.com | Completed | 1 |
| example.com | No email | 0 |
| company.com | Restricted | 0 |
| business.com | Retry | 0 |
This prevents the scraper from repeatedly processing the same websites.
Step 28: Use a Queue
For larger jobs, create a queue:
URL 1 → Pending
URL 2 → Pending
URL 3 → Pending
URL 4 → Pending
Workers retrieve URLs:
Worker 1 → URL 1
Worker 2 → URL 2
Worker 3 → URL 3
Worker 4 → URL 4
When finished:
URL 1 → Completed
URL 2 → Completed
URL 3 → Error
URL 4 → Completed
This is much more reliable than one enormous loop.
Step 29: Use Concurrency Carefully
Concurrency means processing multiple websites at the same time.
Instead of:
Website A
↓
Website B
↓
Website C
↓
Website D
you can process:
Website A ──┐
Website B ──┤
Website C ──┼──→ Workers
Website D ──┤
Website E ──┘
This can dramatically reduce total processing time because web requests are largely I/O-bound.
But concurrency should be controlled, particularly per domain. Sending ten simultaneous requests to ten different domains is very different from sending ten requests simultaneously to one domain.
Step 30: Use Domain-Level Rate Limits
A common mistake is having:
20 workers
all accessing:
example.com
at once.
Instead, establish limits such as:
Maximum simultaneous requests per domain: 1–2
while allowing work across many different domains.
This improves reliability and reduces unnecessary server load. Current crawling guidance recommends deliberate throttling and domain-aware concurrency.
Step 31: Handle HTTP Errors
Your scraper should understand common responses.
200
Success
301/302
Redirect
403
Forbidden
404
Not found
429
Too many requests
500+
Server error
If you receive a 429 response, don’t immediately send more requests. Pause and follow any applicable Retry-After guidance. Repeated 403 responses should generally trigger a stop or review rather than increasingly aggressive retries
Step 32: Use Retries Carefully
A temporary network failure might justify:
Retry 1
↓
Wait
↓
Retry 2
↓
Wait longer
↓
Retry 3
This is called backoff.
Don’t use unlimited retries.
Otherwise:
Website unavailable
↓
Retry
↓
Retry
↓
Retry
↓
Retry
can create unnecessary traffic.
Step 33: Cache Results
If you already downloaded:
https://example.com/contact
don’t unnecessarily download it again.
Store:
URL
HTML/content
Date
Status
Then reuse the existing content where appropriate.
Caching reduces:
- Network traffic
- Processing time
- Duplicate requests
- Server load
Caching and incremental crawling are recommended practices for reliable large-scale scraping.
Step 34: Use Sitemaps
Some websites publish:
/sitemap.xml
A sitemap can help identify pages without crawling every link from the homepage.
For example:
sitemap.xml
↓
/about
/contact
/team
/services
/blog
You can then prioritize pages relevant to email discovery.
Using sitemaps is specifically recommended as an efficient way to focus crawling on important pages
Step 35: Keep a Crawl Log
For each request, store information such as:
timestamp
domain
URL
HTTP status
response time
emails found
error
Example:
| Domain | URL | Status | Emails | Time |
|---|---|---|---|---|
| abc.com | / | 200 | 1 | 1.2s |
| abc.com | /contact | 200 | 2 | 1.5s |
| xyz.com | / | 403 | 0 | 0.8s |
This is invaluable when troubleshooting.
Step 36: Handle Website Changes
A website might change:
Old:
<div class="contact-email">
New:
<div data-contact="email">
A scraper that relies heavily on fragile CSS selectors can suddenly stop working.
Prefer robust extraction approaches based on:
- Semantic elements
- Link types
- Stable attributes
- Text patterns
- Page context
rather than highly specific generated CSS classes.
Python Architecture for Multiple Websites
A basic architecture can look like:
websites = [
"https://example1.com",
"https://example2.com",
"https://example3.com"
]
for website in websites:
pages = discover_relevant_pages(website)
for page in pages:
html = fetch_page(page)
emails = extract_emails(html)
save_results(website, page, emails)
The important concept is not the exact code.
It is the separation of:
Website discovery
↓
Page discovery
↓
Fetching
↓
Extraction
↓
Cleaning
↓
Storage
A Better Production Architecture
For a larger system:
┌───────────────┐
│ Website Input │
└───────┬───────┘
↓
┌───────────────┐
│ URL Validator │
└───────┬───────┘
↓
┌───────────────┐
│ Crawl Queue │
└───────┬───────┘
↓
┌──────────┴──────────┐
↓ ↓ ↓
Worker 1 Worker 2 Worker 3
↓ ↓ ↓
Fetch Fetch Fetch
└──────────┬──────────┘
↓
┌───────────────┐
│ Email Parser │
└───────┬───────┘
↓
┌───────────────┐
│ Data Cleaning │
└───────┬───────┘
↓
┌───────────────┐
│ Deduplication │
└───────┬───────┘
↓
┌───────────────┐
│ Verification │
└───────┬───────┘
↓
┌───────────────┐
│ Database/CSV │
└───────────────┘
Scraping 10 Websites
For 10 websites, you can keep the system simple.
Input CSV
↓
Python
↓
Requests
↓
BeautifulSoup
↓
Regex
↓
CSV
You probably don’t need elaborate infrastructure.
Scraping 100 Websites
At 100 websites, add:
- URL validation
- Status tracking
- Duplicate removal
- Retries
- Logging
- Basic concurrency
- Domain rate limits
Scraping 1,000 Websites
At 1,000 websites, consider:
- Queue
- Worker pool
- Database
- Caching
- Per-domain throttling
- Better error handling
- Browser rendering when necessary
Scraping 10,000+ Websites
At this scale, consider:
Database
+
Queue
+
Workers
+
Monitoring
+
Caching
+
Domain scheduler
+
Structured logging
The technical problem becomes an infrastructure problem as much as a scraping problem.
Example Data Model
A database table might contain:
website_id
company_name
domain
page_url
email
email_type
crawl_date
verification_status
crawl_status
You could also create separate tables:
websites
pages
emails
crawl_jobs
verification_results
This avoids putting everything into one enormous table.
Example Output
Suppose you process five websites.
The raw extraction might produce:
info@company-a.com
info@company-a.com
sales@company-a.com
hello@company-b.com
hello@company-b.com
support@company-c.com
After normalization and deduplication:
info@company-a.com
sales@company-a.com
hello@company-b.com
support@company-c.com
Your final CSV could be:
| Company | Type | Source | |
|---|---|---|---|
| Company A | info@company-a.com | General | /contact |
| Company A | sales@company-a.com | Sales | /contact |
| Company B | hello@company-b.com | General | / |
| Company C | support@company-c.com | Support | /support |
Measuring Performance
Don’t judge your scraper only by speed.
Track:
Website success rate
Successful websites
÷
Total websites
Email discovery rate
Websites producing emails
÷
Websites successfully crawled
Duplicate rate
Duplicate emails
÷
Raw email matches
Verification rate
Verified addresses
÷
Unique extracted addresses
Relevant-contact rate
Relevant contacts
÷
Unique extracted addresses
These metrics give you a much better understanding of the quality of the system.
Example Performance Report
Imagine processing 1,000 permitted websites:
Websites submitted: 1,000
Successfully crawled: 850
No email found: 300
Websites with email: 550
Raw email matches: 1,800
Unique emails: 1,350
Verified/usable: 1,000
Generic addresses: 720
Individual addresses: 280
This tells you much more than:
“We scraped 1,800 emails.”
Common Problems When Scraping Multiple Websites
Problem 1: Some websites work and others don’t
This is normal.
Different websites use different technologies.
Solution
Build multiple extraction strategies:
Static HTML
+
mailto
+
Rendered browser
Problem 2: Too Many Websites Return 403
Possible causes include:
- Website restrictions
- Excessive request rate
- Automated-access controls
Solution
Do not simply increase request volume or attempt to defeat the restriction.
Instead:
- Check access rules
- Reduce traffic
- Respect the site’s restrictions
- Stop where access is prohibited
- Use an official API if available
Problem 3: Too Many 429 Errors
A 429 generally indicates excessive request frequency.
Solution
Implement:
Rate limit
+
Backoff
+
Retry-After handling
Problem 4: Scraper Takes Too Long
Possible causes:
- Sequential requests
- Excessive crawl depth
- Slow websites
- Browser rendering on every page
- No caching
Solution
Use:
Controlled concurrency
+
Page prioritization
+
Caching
+
Timeouts
Problem 5: Too Many False Positives
The scraper might find strings such as:
image@example.com
test@example.com
example@example.com
or email-like strings inside unrelated content.
Solution
Use:
- Better parsing
- Context filtering
- Domain checks
- Deduplication
- Validation
- Manual sampling
Problem 6: Too Many Duplicates
This often happens because the same address appears in:
- Header
- Footer
- Contact page
- About page
- Multiple team pages
Solution
Normalize and deduplicate globally.
Problem 7: JavaScript Pages Return Nothing
Solution
Determine whether the email is actually present in the rendered page.
If so, use authorized browser rendering.
If the address isn’t publicly exposed, don’t attempt to manufacture it.
Problem 8: Contact Forms Instead of Emails
Your result should say:
Contact form available
rather than:
No information
A contact form can still be valuable business information.
Problem 9: Old Emails
Websites may contain historical documents.
For example:
2019 annual report
could contain:
formeremployee@company.com
Store:
source_date
crawl_date
document_date
where available.
Problem 10: The Same Company Has Multiple Domains
For example:
company.com
company.co.uk
company.eu
You may want to group them under:
Company Name
while preserving the individual domains.
Legal and Ethical Considerations
Email scraping from multiple websites requires more care than a small one-site experiment.
Before starting:
Check website rules
Review:
robots.txt
Terms of Service
Avoid private information
Do not scrape:
- Login-protected pages
- Private databases
- Private accounts
- Information requiring unauthorized access
Minimize collection
Collect only what you actually need.
Protect stored data
If your dataset contains personal information, secure it appropriately.
Consider applicable privacy laws
Depending on your location, the website, and intended use, data-protection and electronic-marketing laws may apply.
Current guidance specifically emphasizes public business contacts, lawful processing, secure storage, and responsible outreach.
Scraping and Email Marketing Are Separate Steps
This distinction is extremely important.
Your workflow might be:
Website scraping
↓
Email extraction
↓
Verification
↓
Compliance review
↓
Marketing decision
Finding an email does not automatically give you permission to send unsolicited marketing messages.
If your objective is marketing, separately evaluate:
- Applicable email-marketing laws
- Lawful basis
- Consent requirements
- Opt-out requirements
- Suppression lists
- Business-to-business rules
- Geographic requirements
How to Make the Process More Efficient
Use targeted crawling
Don’t crawl everything.
Prioritize:
/contact
/about
/team
/leadership
/press
/support
Use batches
Instead of:
10,000 websites
run:
Batch 1: 100
Batch 2: 100
Batch 3: 100
This makes errors easier to identify and recover from. Batch processing is also recommended in crawling guidance to reduce excessive simultaneous load.
Cache completed pages
Avoid downloading the same page repeatedly.
Store failures
Don’t lose URLs that failed.
Create:
retry_queue.csv
or a database queue.
Separate extraction from verification
Do:
Crawler
↓
Raw database
↓
Cleaning
↓
Verification
rather than performing everything in one step.
This makes the system easier to debug.
Recommended Technology Stack
Beginner
Python
Requests
BeautifulSoup
Regular Expressions
CSV
Best for:
- Small projects
- Simple websites
- Learning
Intermediate
Python
Requests
BeautifulSoup
Selenium/Playwright
Pandas
SQLite/PostgreSQL
Best for:
- Hundreds or thousands of websites
- JavaScript-heavy websites
- Structured datasets
Advanced
Python
Async HTTP
Browser automation
Queue
Database
Caching
Monitoring
Domain scheduler
Best for:
- Large-scale projects
- Recurring crawls
- Enterprise research systems
A Practical Multi-Website Strategy
If your goal is to process hundreds of business websites, a strong workflow is:
Phase 1 — Input
Website list
Phase 2 — Validation
Valid domain?
Accessible?
Permitted?
Phase 3 — Discovery
Homepage
↓
Contact
↓
About
↓
Team
↓
Press
Phase 4 — Extraction
mailto
+
visible text
+
authorized rendered content
Phase 5 — Cleaning
Normalize
↓
Remove false positives
↓
Deduplicate
Phase 6 — Classification
General
Sales
Support
Press
Careers
Individual
Phase 7 — Verification
Syntax
↓
Domain
↓
Deliverability signals
Phase 8 — Storage
CSV
Database
CRM
Phase 9 — Compliance
Purpose
+
Privacy
+
Outreach rules
+
Opt-outs
Final Checklist
Before running a multi-website email scraper, check:
- Website list prepared
- Duplicate domains removed
- URLs normalized
- API alternatives checked
-
robots.txtreviewed - Terms reviewed
- Crawl scope defined
- Maximum crawl depth established
- Domain rate limits configured
- Timeouts configured
- Retry/backoff implemented
- JavaScript strategy defined
-
mailto:extraction enabled - Email pattern extraction enabled
- Normalization implemented
- Deduplication implemented
- Source URLs stored
- Crawl status stored
- Verification process defined
- Personal-data handling considered
- Outreach compliance considered
Conclusion
Scraping emails from multiple websites is best understood as a multi-stage data collection system, not simply a regular-expression exercise.
For a small project:
CSV
↓
Python
↓
Website
↓
Extract
↓
Clean
↓
Export
may be enough.
For hundreds or thousands of websites:
Website Database
↓
URL Queue
↓
Controlled Workers
↓
Domain-Level Rate Limits
↓
Page Discovery
↓
HTML/Browser Extraction
↓
Email Detection
↓
Normalization
↓
Deduplication
↓
Verification
↓
Database
is a much stronger architecture.
The most important principle is quality over raw volume. A responsible multi-site scraper should know which websites it is allowed to crawl, limit its impact on each server, distinguish genuine email addresses from false positives, preserve the source of every result, and clearly separate extracted information from inferred or guessed information. Current web-crawling guidance also recommends throttling, caching, batching, handling 429 responses appropriately, and respecting site-specific crawling rules.
For legitimate business research, the end goal should not simply be “scrape as many emails as possible.” It should be “build an accurate, current, traceable, and appropriately collected business-contact dataset.”
How to Scrape Emails From Multiple Websites – Case Studies and Comments
Scraping emails from multiple websites can save substantial research time when a business needs to process hundreds or thousands of permitted websites. The most effective workflows generally combine website discovery, targeted page crawling, email extraction, normalization, deduplication, source tracking, and verification rather than simply searching every page for an @ symbol.
Below are practical case studies and comments showing how these approaches work in real-world situations.
Case Study 1: Processing 4,500 Websites for Brand Research
Background
A brand-protection research project began with a much larger collection of potentially relevant websites. Researchers narrowed the dataset to approximately 4,500 domains that appeared most relevant to the brand being investigated.
The team then automatically inspected website HTML and extracted strings matching the general format of an email address. At least one email was found on just over 1,000 of the sites when focusing on homepages.
Workflow
Large website dataset
↓
Identify relevant domains
↓
Prioritize approximately 4,500 domains
↓
Inspect HTML
↓
Extract email patterns
↓
Compare addresses across domains
↓
Cluster related websites
What Made the Case Interesting?
The researchers weren’t interested only in collecting emails.
They examined which email addresses appeared on multiple websites.
For example:
Website A → info@example-provider.com
Website B → info@example-provider.com
Website C → info@example-provider.com
The shared address could provide a clue that the websites were connected.
Comment
This demonstrates that an email address can function as a data relationship, not merely a contact detail.
However, researchers must be careful: a common email address can also belong to a shared service provider and does not automatically prove that two businesses are related
Case Study 2: Automating Agency Prospect Research
Background
A marketing agency had a list of company websites and needed to identify publicly displayed business email addresses.
The manual workflow was:
Open website
↓
Find Contact
↓
Copy email
↓
Return to spreadsheet
↓
Open next website
When hundreds of websites were involved, this became extremely repetitive.
Automated Workflow
CSV of websites
↓
Website crawler
↓
Homepage
↓
Contact/About/Team pages
↓
Email extraction
↓
Normalization
↓
CSV/database
Modern website-extraction systems commonly support multiple URLs in one run, bounded same-site crawling, contact-page prioritization, deduplication, and source-page tracking.
Comment
The important improvement isn’t simply speed.
The system also creates a consistent structure:
| Company | Website | Source | |
|---|---|---|---|
| Company A | companya.com | info@companya.com | /contact |
| Company B | companyb.com | sales@companyb.com | /sales |
| Company C | companyc.com | hello@companyc.com | / |
This makes the resulting data easier to review and import into other systems.
Case Study 3: Processing 500 Companies Instead of Browsing Manually
Background
A workflow provider described a scenario involving 500 companies.
At an estimated 10 minutes of manual research per company, the work would represent approximately:
83 hours of manual effort.
The automated approach instead accepted a list of domains and processed them in bulk.
Manual Process
Company 1 → 10 minutes
Company 2 → 10 minutes
Company 3 → 10 minutes
...
Company 500 → 10 minutes
Automated Process
500 websites
↓
Batch processing
↓
Website crawling
↓
Email extraction
↓
Structured dataset
Comment
This illustrates one of the strongest reasons to automate multiple-website extraction:
repetitive navigation is replaced with batch processing.
However, automation doesn’t eliminate the need for quality control.
A scraper can process 500 websites quickly while still returning:
- Duplicate addresses
- Old addresses
- Generic addresses
- False positives
- Websites with no email
- Contact forms instead of emails
Case Study 4: B2B Email Extractor Using CSV Input
Background
A developer created a B2B email extraction tool to address the problem of manually researching company websites.
The tool accepted a Google Maps export or another CSV containing companies and websites, then scanned homepages and deeper website pages for corporate email addresses.
Workflow
Google Maps/CSV
↓
Company list
↓
Website URL
↓
Homepage
↓
Deep subpages
↓
Corporate emails
Why Deep Pages?
A homepage may contain:
Company information
Services
Phone
while the actual email appears on:
/contact
/team
/about
/support
Comment
This is one of the most important lessons in multi-site scraping:
A website should not be treated as a single webpage.
A targeted crawler can improve discovery by following relevant internal pages.
Case Study 5: Google Maps Businesses → Websites → Emails
Background
Another workflow begins with a list of businesses rather than websites.
The system first identifies businesses, obtains their websites, and then attempts to locate email addresses on those websites.
Workflow
Business category
↓
Business listings
↓
Company website
↓
Contact pages
↓
Email extraction
↓
Spreadsheet
A 2026 workflow example describes using n8n to find businesses, visit their websites for email addresses, and then handle cases where websites don’t expose an email.
Comment
This approach is particularly useful for:
- Local service businesses
- Suppliers
- Agencies
- Contractors
- Retailers
- Professional services
The website becomes the second stage of the research process.
Case Study 6: Email Extraction Plus Social Profiles
Background
Some bulk website workflows don’t stop at email addresses.
They extract:
- X/Twitter
from each company website.
One current workflow accepts multiple domains and returns a primary email, additional email addresses, and social profiles in a structured dataset.
Example
Company A
├── info@company.com
├── sales@company.com
├── LinkedIn
└── Instagram
Comment
This creates a richer prospect record than an email-only database.
For example:
| Company | |||
|---|---|---|---|
| Company A | info@a.com | Found | Found |
| Company B | sales@b.com | Found | Not found |
| Company C | — | Found | Found |
Case Study 7: Structured Email Extraction With Source Tracking
A more sophisticated approach stores not just the email but where the email was found.
For example:
Email:
sales@example.com
Source:
https://example.com/contact
Original website:
https://example.com
Discovery method:
mailto-link
Modern extraction systems can record source URLs and discovery context, such as whether the address appeared in a mailto: link, visible text, or supported obfuscated text)
Comment
This is much better than maintaining a simple list:
sales@example.com
info@example.com
hello@example.com
because you can later answer:
“Where did this email come from?”
That makes auditing and data-quality review easier.
Case Study 8: Extracting Emails From 10,000+ Domains
Background
Large-scale website scraping becomes a different engineering problem.
A practitioner attempting to process more than 10,000 domains reported that a custom crawler was faster than manual browsing but initially missed emails that were easy to find manually
The Problem
A basic crawler might do:
Homepage
↓
Regex
↓
Email
But real websites may have:
Homepage
↓
Contact page
↓
Team page
↓
JavaScript
↓
Footer
↓
PDF
Comment
This is a critical lesson:
Speed doesn’t compensate for poor coverage.
A scraper that processes 10,000 websites but misses half the useful information may be less valuable than a slower system with better page discovery.
Case Study 9: Website Contact Pages and Decision-Makers
Background
A B2B prospecting workflow focused on company websites to identify:
- Emails
- Team members
- Decision-makers
- Contact pages
The approach was to crawl live company websites and rank potential contacts according to their usefulness for prospecting. A published 2026 case study reports processing 100 sites in under a minute in its particular implementation.
Workflow
Company websites
↓
Contact pages
↓
Team pages
↓
Email extraction
↓
Employee identification
↓
Contact ranking
Comment
This demonstrates an important distinction.
Email scraping answers:
What email addresses are publicly displayed?
Decision-maker research answers:
Who is the appropriate person to contact?
These are related but different problems.
Case Study 10: Website Email Extraction for Research
Background
A research team wants to build a database of companies in a particular industry.
Instead of collecting only emails, it creates a structured record.
Company
Website
Industry
Country
Email
Email type
Source page
Date collected
Example
ABC Logistics
abc-logistics.com
Logistics
United Kingdom
info@abc-logistics.com
General
/contact
2026-08-25
Comment
This is particularly useful for:
- Market research
- Industry analysis
- Academic research
- Competitor mapping
- Supplier research
The email is only one field in the dataset.
Case Study 11: Scraping Websites for Supplier Research
Background
An e-commerce business wants to identify potential suppliers.
It creates a list of supplier websites and processes them in bulk.
Workflow
Supplier websites
↓
Homepage
↓
Wholesale page
↓
Contact page
↓
Sales email
↓
Supplier database
Data Collected
Company
Product category
Website
Sales email
Wholesale email
Phone
Country
Comment
This is a good example of how website extraction can be useful without immediately turning the results into a marketing list.
The data can support:
- Procurement
- Sourcing
- Vendor discovery
- Partnership research
Case Study 12: Recruitment Research
Background
A recruitment company wants to identify publicly listed employer contacts.
Instead of trying to generate private email addresses, it looks for explicitly published business channels.
Examples include:
careers@company.com
recruitment@company.com
jobs@company.com
Workflow
Company website
↓
Careers page
↓
Recruitment information
↓
Public email
↓
Recruitment database
Comment
This is more reliable than assuming an employee’s email address based on a naming pattern.
For example, if a website doesn’t publish:
john.smith@company.com
the scraper shouldn’t pretend that an inferred address was actually found.
Case Study 13: Scraping Only High-Value Pages
Background
A company initially crawled every page on every domain.
This created unnecessary work.
A website might contain:
200 blog posts
50 product pages
10 service pages
1 contact page
If the objective is email discovery, crawling every blog post isn’t necessarily efficient.
Improved Workflow
Homepage
↓
Identify relevant links
↓
Contact
About
Team
Support
Press
Careers
↓
Extract
Some current extraction systems deliberately use bounded crawling and prioritize contact-related pages instead of performing unrestricted whole-site crawling
Comment
Targeted crawling is usually better than blind crawling for contact discovery.
Case Study 14: Separating Emails by Type
Suppose a crawler finds:
info@example.com
sales@example.com
support@example.com
press@example.com
john@example.com
Instead of storing them all identically, classify them.
| Type | |
|---|---|
| info@example.com | General |
| sales@example.com | Sales |
| support@example.com | Support |
| press@example.com | Media |
| john@example.com | Individual |
Comment
This improves the usefulness of the dataset.
A company doing partnership research may want:
partnership@
business@
sales@
while a journalist may prefer:
press@
media@
communications@
Case Study 15: Deduplicating Thousands of Results
Background
A crawler processes 1,000 websites.
It finds:
2,500 raw email matches
But many addresses appear repeatedly.
For example:
Homepage → info@example.com
About → info@example.com
Contact → info@example.com
Footer → info@example.com
After deduplication:
1,600 unique email addresses
Comment
This demonstrates why:
raw email count ≠ useful email count.
A good system should distinguish:
Raw matches
Unique addresses
Verified addresses
Relevant addresses
Case Study 16: Contact Form Instead of Email
Background
A crawler processes 1,000 websites.
Some websites return:
Email found: 600
Others:
Contact form: 200
Others:
Phone only: 100
And some:
No obvious contact channel: 100
Comment
A contact-form-only result shouldn’t necessarily be treated as a technical failure.
The website may deliberately choose not to publish an email address.
A mature dataset can therefore contain:
email
contact_form_url
phone
no_contact
rather than forcing every website into an email/no-email binary.
Case Study 17: Extracting Only Publicly Displayed Emails
A modern lightweight extraction workflow can be deliberately restricted to:
Public page
↓
Visible email
OR
mailto link
OR
supported public obfuscation
It does not generate guessed employee addresses or access pages behind authentication
Comment
This is a useful design principle:
Extraction should be different from guessing.
If the website displays:
sales@example.com
record it.
If the website only displays:
John Smith
don’t automatically turn that into:
john.smith@example.com
and label it “scraped.”
Case Study 18: Using Email Addresses to Discover Website Relationships
The 2025 brand-protection case study provides another interesting application.
Researchers found the same email address appearing on different domains and used that information as one possible clue for establishing relationships between websites
Example
Website A
info@shared-domain.com
Website B
info@shared-domain.com
Website C
info@shared-domain.com
This creates a potential relationship:
A ──┐
B ──┼── Shared email
C ──┘
Comment
This can be useful for:
- Brand protection
- OSINT research
- Investigative research
- Network analysis
But shared infrastructure can produce false associations, so an email match should be treated as a lead for further investigation, not proof of ownership.
Case Study 19: Building a Multi-Website Spreadsheet
For a small company, a sophisticated database may not be necessary.
A spreadsheet can contain:
| Website | Type | Source Page | Status | |
|---|---|---|---|---|
| company1.com | info@company1.com | General | /contact | Review |
| company2.com | sales@company2.com | Sales | /about | Review |
| company3.com | — | — | /contact | Form only |
Workflow
Website CSV
↓
Scraper
↓
CSV output
↓
Excel/Google Sheets
↓
Manual review
Comment
The best system is not necessarily the most sophisticated one.
For 50–200 websites, a spreadsheet-based workflow may be completely adequate.
Case Study 20: Large-Scale Automated Workflow
At much larger scale, a production system may look like:
Website List
↓
URL Normalization
↓
Crawl Queue
↓
┌────────────┼────────────┐
↓ ↓ ↓
Worker 1 Worker 2 Worker 3
↓ ↓ ↓
Website Website Website
└────────────┼────────────┘
↓
Page Discovery
↓
Email Extraction
↓
Normalization
↓
Deduplication
↓
Quality Checking
↓
Database
Comment
At this point, the biggest challenge is no longer regex.
It becomes:
- Queue management
- Concurrency
- Rate control
- Error handling
- Storage
- Monitoring
- Data quality
- Website changes
Comments From Practitioners
Comment 1: “Deep scanning makes a difference”
Practitioners repeatedly point out that emails aren’t necessarily located on the homepage.
They can appear on:
- Contact pages
- Team pages
- About pages
- Footer
- Staff pages
- Support pages
A 2026 community project specifically describes scanning homepages and then deep-scanning subpages to find corporate email addresses.
Lesson
Don’t build a crawler that assumes:
Homepage = entire website
Comment 2: “Manual browsing can find things a basic crawler misses”
A practitioner processing more than 10,000 domains reported that a custom crawler was much faster than manual browsing but less accurate initially
Lesson
Automation needs testing against real websites.
Don’t assume that:
“The script ran successfully”
means:
“The scraper found everything.”
Comment 3: “Generic emails dominate”
A major problem with website email scraping is that many published addresses are role-based:
info@
contact@
sales@
support@
hello@
These can be genuine and useful, but they usually aren’t equivalent to a named decision-maker address.
Lesson
Classify addresses instead of treating every result as a direct contact.
Comment 4: “Source tracking is extremely valuable”
Suppose your database contains:
sales@example.com
Six months later, someone asks:
Where did this come from?
Without provenance, you may have to search for the answer again.
With source tracking:
Email: sales@example.com
Source: example.com/contact
Collected: August 25, 2026
the answer is immediate.
Current extraction systems increasingly preserve source-page information for exactly this reason.
Comment 5: “Don’t guess email addresses”
If a website publishes:
john.smith@example.com
it can be extracted.
If the website publishes only:
John Smith
creating:
john.smith@example.com
is a different operation.
Lesson
Maintain a clear distinction between:
observed
and
inferred.
Comment 6: “Verification is separate from extraction”
A scraper can tell you:
sales@example.com
was displayed on a page.
It cannot automatically prove:
The mailbox is currently active.
Email-extraction systems explicitly distinguish extraction from mailbox verification
Lesson
Use a separate verification stage when the project requires deliverability information.
Comment 7: “A contact form isn’t a failure”
Some websites intentionally don’t publish emails.
Instead they provide:
Contact form
or:
Book a consultation
Lesson
Store:
contact_form_url
rather than marking the website as completely useless.
Comment 8: “Start with a small batch”
A good workflow is:
10 websites
↓
Test
↓
50 websites
↓
Test
↓
100 websites
↓
Scale
This allows you to discover:
- False positives
- Missing emails
- Website compatibility problems
- Rate-limit issues
- Duplicate problems
before processing thousands of domains.
Comment 9: “Targeted crawling beats unlimited crawling”
If you’re looking for contact information, prioritize pages such as:
/contact
/about
/team
/staff
/support
/press
instead of crawling every blog article.
Current multi-site extraction tools commonly use bounded page counts and contact-related link filtering to control crawl expansion.
Comment 10: “Don’t measure success by raw email volume”
Imagine two systems:
System A
10,000 raw matches
System B
5,000 unique
4,200 clean
3,600 relevant
System B may be much more useful.
Better metrics
Measure:
- Websites successfully processed
- Websites with emails
- Unique emails
- Duplicate rate
- Verification rate
- Relevant-contact rate
- Contact-form rate
Comment 11: “Website scraping is useful for more than lead generation”
The same technology can support:
- Market research
- Supplier discovery
- Recruitment
- Brand protection
- Academic research
- Competitor analysis
- Business intelligence
- Website auditing
The brand-protection case demonstrates how extracted emails can also be used as signals for identifying relationships among online properties.
Comment 12: “The website may contain more valuable information than the email”
Suppose a website gives you:
Company
Industry
Products
Location
Leadership
Contact email
Social profiles
The complete company profile may be much more valuable than:
info@example.com
This is why many modern website-extraction workflows combine emails with phone numbers, social profiles, company information, and source URLs
Case Study Comparison
| Case Study | Main Objective | Main Lesson |
|---|---|---|
| 4,500-domain research | Brand investigation | Email addresses can reveal relationships |
| Agency prospecting | Reduce manual work | Batch processing improves efficiency |
| 500-company workflow | Automate research | Automation can replace repetitive browsing |
| B2B extractor | Corporate contact discovery | Deep pages matter |
| Business-to-website workflow | Local lead research | Business lists can feed website crawling |
| Social + email extraction | Enrichment | Email is only one data point |
| Source-tracked extraction | Data quality | Provenance matters |
| 10,000+ domains | Large-scale scraping | Architecture becomes critical |
| Decision-maker research | B2B prospecting | Email extraction and contact identification differ |
| Supplier research | Procurement | Scraping has non-marketing uses |
What These Case Studies Teach
1. Multiple websites require structured processing
Don’t manually open one website after another.
Use:
Input
↓
Queue
↓
Crawler
↓
Extractor
↓
Database
2. Homepage-only extraction is often insufficient
Prioritize relevant internal pages.
3. Email extraction isn’t email verification
An address being publicly displayed doesn’t guarantee that the mailbox remains active.
4. Generic addresses are common
Expect many:
info@
contact@
sales@
support@
rather than named decision-makers.
5. Source URLs should be preserved
Always know where each email came from.
6. Don’t confuse inference with extraction
A guessed email shouldn’t be presented as a scraped email.
7. Quality matters more than volume
A smaller, clean, traceable dataset can be more useful than a huge raw list.
Recommended Multi-Website Workflow
Based on the case studies, a strong workflow is:
1. Prepare permitted website list
↓
2. Normalize domains
↓
3. Remove duplicates
↓
4. Review access/usage rules
↓
5. Check for official APIs where appropriate
↓
6. Crawl homepage
↓
7. Discover contact-related pages
↓
8. Extract publicly displayed emails
↓
9. Record source URL
↓
10. Normalize addresses
↓
11. Remove duplicates
↓
12. Classify addresses
↓
13. Verify where appropriate
↓
14. Export structured data
↓
15. Review before use
Example Final Dataset
After processing multiple websites, a useful final dataset might look like:
| Company | Domain | Type | Source | Status | |
|---|---|---|---|---|---|
| ABC Ltd | abc.com | info@abc.com | General | /contact | Review |
| ABC Ltd | abc.com | sales@abc.com | Sales | /contact | Review |
| XYZ Inc | xyz.com | hello@xyz.com | General | / | Review |
| Global Services | global.com | support@global.com | Support | /support | Review |
| Example Co | example.com | — | Contact form | /contact | Form |
This is significantly more useful than a raw list of email addresses because it preserves company identity, domain, email type, source, and status.
Final Comments
The case studies show that scraping emails from multiple websites is most effective when it is treated as a structured research and data-quality workflow, rather than simply an exercise in collecting as many addresses as possible.
The strongest systems generally follow this model:
Multiple Websites
↓
Targeted Crawling
↓
Relevant Pages
↓
Public Email Extraction
↓
Normalization
↓
Deduplication
↓
Classification
↓
Verification
↓
Source Tracking
↓
Structured Database
The biggest practical lesson is quality over quantity. A system that extracts 5,000 accurately sourced and properly classified addresses can be more valuable than one that produces 20,000 raw matches with duplicates, stale addresses, false positives, and no source information.
It is also important to remember that finding a publicly displayed email does not automatically establish permission to send marketing messages to it. Website collection and subsequent email use are separate questions and should be evaluated under the applicable website rules, privacy requirements, and marketing laws.
For legitimate business research, the ideal objective is therefore not:
“How many emails can I scrape?”
but:
“How can I build an accurate, traceable, appropriately collected contact dataset from the websites I am permitted to process?”
