Blog
API GuidesJune 13, 202615 min read

How to Extract Emails From Any Website (2026 Guide)

Extract emails from any website: manual methods, regex, Python scripts, plus how to pull deduped on-domain contact emails at scale from a city search.

A website page source transforming into a clean, deduped list of business contact emails.

If you need to extract emails from a website, the honest answer is that there is no single button that always works. Some sites print a clean mailto: link in the footer, some bury the address in an image, some hide it behind a contact form, and some scatter several addresses across an impressum, a team page, and a careers page. This guide walks through every practical method, from viewing the page source by hand to writing a Python script, and is honest about where each one breaks. Then it shows how biz collect does website email extraction at scale, turning a city and a set of keywords into structured business records with deduped contact emails pulled from the businesses' own domains.

Why Email Extraction Is Harder Than It Looks

The phrase "extract emails from any website" promises more than any tool can deliver, so it helps to be clear about what is actually happening. A business email lives somewhere in the HTML, the rendered page, a linked document, or sometimes only inside a form submission that the site never exposes as a readable address. Each of those storage locations needs a different extraction approach, and a real business often uses more than one.

Here are the patterns you will run into:

  • A plain mailto: link. The easiest case. The address is right there in the HTML, usually in the footer or on a contact page.
  • Plain text on the page. The address is visible but not linked, for example hello [at] example dot com written to dodge naive scrapers.
  • A separate contact, about, or impressum page. The homepage has no address, but a linked page does. German, Austrian, and Swiss sites are legally required to publish an impressum, which is often the best single source.
  • A contact form only. No address anywhere, just a form. This is a genuine dead end for direct extraction.
  • An image or obfuscated address. The address is rendered as an image, or assembled by JavaScript, specifically to defeat extraction.
  • Multiple addresses. Info, sales, support, and a named owner, spread across several pages, often with duplicates.

Any method you choose is really a tradeoff between effort and coverage. Manual inspection is the most accurate per site and the slowest. Scripts and APIs are fast but miss the obfuscated and form-only cases. Knowing this upfront keeps your expectations honest and your outreach list clean.

Method 1: View the Page Source by Hand

The fastest way to find an email on a single website is to read the HTML directly. In any browser, press Ctrl+U (Cmd+Option+U on Safari after enabling the develop menu) to open the page source, then use Ctrl+F to search.

Search for these, in order:

  1. mailto: finds every linked email on the page instantly.
  2. @ catches plain-text addresses, though it also matches social handles and other noise.
  3. email, contact, or kontakt as words often sit near the address in the markup.

If the homepage has nothing, open the contact, about, team, imprint, or impressum page and repeat. This sounds tedious, but for a single high-value prospect it takes under a minute and you see exactly what is there, including notes about which inbox is which. For an authoritative reference on how mailto: links are structured, the MDN documentation on email links is worth a quick read.

The limit is obvious: this does not scale. Ten prospects is fine. A thousand local businesses is not. That is where the next methods come in.

Method 2: Browser Tools and Extensions

A step up from manual inspection is a browser-based extractor. Browser extensions can scan the current page (and sometimes linked pages) for email patterns and dump them into a list you can copy.

These tools are convenient for a handful of pages and require no code. They share the same ceiling as manual inspection plus a few new caveats:

  • They typically read only the page you are on, or a shallow set of linked pages, so they miss addresses on deeper contact or impressum pages.
  • They cannot see addresses rendered as images or assembled by JavaScript after load.
  • Many extensions request broad permissions, so review what a given extension can access before installing it.
  • Output is rarely deduped or validated, so you still get the same address three times and the occasional image@2x.png false positive.

Browser extractors are a reasonable middle ground for quick, low-volume work. For repeatable, larger jobs you want either a script you control or an API that handles traversal and deduplication for you.

Method 3: Regex and a View-Source Workflow

If you are comfortable with a little text processing, a regular expression turns raw page source into a clean list of candidate addresses. The classic email regex is a balance between catching real addresses and avoiding false matches:

[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}

The workflow is simple. Save the page source to a file, run the pattern over it, then dedupe the results. On most systems you can do this without writing a program at all:

# Save a page, then extract unique email-shaped strings from it
curl -s https://example.com | grep -Eio '[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}' | sort -u

This is fast and transparent, and it works on the raw HTML for any page you can fetch. Be aware of its blind spots:

  • It matches anything email-shaped, so noreply@, tracking-pixel filenames, and example addresses sneak in. Filter those out.
  • It only sees the HTML that curl returns. Pages that build their content with JavaScript will look empty.
  • It does not follow links, so you have to fetch the contact and impressum pages yourself.

A regex pass is the right tool when you have a known list of URLs and want a quick, auditable extraction. For discovery (finding the sites in the first place) and for following the right internal pages automatically, you want a proper script or an API.

Method 4: A Python Script for Multiple Sites

When you have many URLs, a small Python script handles fetching, pattern matching, internal-link following, and deduplication in one pass. Here is a compact version that fetches a page, follows likely contact pages, and returns a deduped set of addresses:

import re
import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup

EMAIL_RE = re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")
CONTACT_HINTS = ("contact", "kontakt", "about", "impressum", "team", "imprint")
SKIP = ("noreply@", "no-reply@", "example.com", "sentry", "wixpress")


def emails_from_html(html: str) -> set[str]:
    found = set(EMAIL_RE.findall(html))
    return {e for e in found if not any(s in e.lower() for s in SKIP)}


def extract_site_emails(base_url: str, timeout: int = 10) -> set[str]:
    emails: set[str] = set()
    try:
        resp = requests.get(base_url, timeout=timeout)
        emails |= emails_from_html(resp.text)
        soup = BeautifulSoup(resp.text, "html.parser")
        for link in soup.find_all("a", href=True):
            href = link["href"].lower()
            if any(hint in href for hint in CONTACT_HINTS):
                page = urljoin(base_url, link["href"])
                try:
                    emails |= emails_from_html(requests.get(page, timeout=timeout).text)
                except requests.RequestException:
                    continue
    except requests.RequestException:
        return emails
    return emails


for url in ["https://example.com", "https://another-example.com"]:
    print(url, sorted(extract_site_emails(url)))

This pattern, fetch the homepage, find contact-style links, follow them, then dedupe and filter, is exactly the shape of real website email extraction. It is also where the maintenance starts. You will eventually need retries, polite rate limiting, a real user agent, JavaScript rendering for some sites, and a discovery step to find the businesses before you can scrape them. None of that is hard individually, but together it becomes a small system to own.

If you want a deeper look at the discovery side and how it differs from page-level scraping, see the glossary entry on web scraping. For a comparison of running your own scripts versus using a structured data source, the post on Google Places API vs scrapers vs business data APIs lays out the tradeoffs clearly.

The Legal and Deliverability Caveats

Extracting an email is a technical step. Using it is a legal and reputational one, and the two are not the same.

On the legal side, scraping publicly visible business contact data is treated very differently across jurisdictions, and cold outreach to those addresses is regulated by laws such as the GDPR, the UK GDPR, the Swiss FADP, CAN-SPAM in the United States, and equivalent rules elsewhere. Business-to-business contact often has a lawful basis under legitimate interest in some regions, but consent, suppression lists, clear identification, and an easy opt-out are commonly required regardless. This article is not legal advice. Before you run outreach, confirm what your jurisdiction and your recipient's jurisdiction require.

On the deliverability side, a scraped list is the fastest way to wreck a sending domain if you treat it carelessly. Generic addresses such as info@ and contact@ are often spam-trap-adjacent, and sending to dead or mistyped addresses spikes your bounce rate. Two habits protect you:

  • Verify before you send. Confirm the mailbox is real and the domain accepts mail. The glossary entry on email verification explains the checks that matter.
  • Warm up and segment. Do not blast an entire scraped list from a cold domain. Start small, prioritize role-appropriate addresses, and remove anything that bounces.

Treating extraction and outreach as separate disciplines is what separates a clean, compliant pipeline from a burned domain.

How biz collect Does Website Email Extraction at Scale

Everything above works for a known list of URLs. The harder problem is the one before that: finding the right businesses in a city and then extracting their contact data without babysitting a scraper. That is the problem biz collect is built for.

You call one async endpoint with a location, keywords, a radius, and an email option. biz collect runs the live local-business search, then visits each business's own website and extracts contact emails from it, following the contact and impressum pages the way the Python script above does, but as a maintained service. You poll the job, and you get back clean structured records.

The request is a single POST:

{
  "location": "Berlin, Germany",
  "keywords": ["dental clinic", "orthodontist"],
  "radius_km": 15,
  "scrape_emails": true
}

You receive a job_id, poll /api/v1/jobs/:id, and read structured businesses when the job completes:

{
  "name": "Example Dental Clinic",
  "address": "Beispielstrasse 12, 10115 Berlin",
  "phone": "+49 30 5550100",
  "website": "https://example-dental.de",
  "emails": ["praxis@example-dental.de", "termin@example-dental.de"]
}

A few design choices matter for email quality specifically:

  • On-domain addresses rank first. An address on the business's own domain, like praxis@example-dental.de, is ranked above a free-provider address like a generic Gmail or Outlook account, because the on-domain inbox is far more likely to be the real business mailbox.
  • Contact and impressum pages are followed. The extractor does not stop at the homepage. It follows the same contact, about, and imprint pages you would check by hand, which is where most real addresses live.
  • Results are deduped. The same address appearing in the header, footer, and contact page collapses to one entry per business, so your list is clean before it reaches your CRM.

For the full request and response shape, see the API docs. To watch the search-then-enrich lifecycle end to end, the how biz collect works page steps through it, and the integrations page shows where it plugs into no-code tools and scripts.

Being Honest About Coverage

A capable extractor still cannot invent an address that is not published. biz collect is deliberately honest about this, and you should be too.

  • Contact-form-only sites return no email. If a business publishes a form and no address, there is nothing to extract. The record will still include the name, address, phone, and website, which often matters more for local outreach than an email anyway.
  • Image-based or heavily obfuscated addresses are skipped. An address rendered as a picture is not text, so it will not appear in the results.
  • Coverage varies by industry and region. Some categories publish addresses freely; others rarely do. A record without an email is not a failure of the search, it is an accurate reflection of what the business chose to publish.

This is why the right mental model is "structured business records, with emails where they exist" rather than "an email for every business." You filter for the records that carry an email when email is required, and you keep the phone-and-website records when a call or a form is the better channel. The post on generating local B2B leads without manual research shows how to build that filtering into a repeatable workflow.

Choosing Your Method

Pick the method that matches your volume and your tolerance for maintenance:

  • One or a few prospects: view the page source by hand. Fastest, most accurate, zero setup.
  • A few dozen known URLs: a browser extractor or a regex pass over fetched HTML.
  • Hundreds of known URLs: a Python script that follows contact pages and dedupes.
  • You need to discover the businesses too, in a city or region: a structured business data API that combines live local search with website email extraction, so you skip both the discovery scraper and the enrichment scraper.

biz collect sits at that last tier. One POST request starts a local business search, async polling returns the structured JSON, on-domain emails rank above free-provider ones, contact and impressum pages are followed, and addresses are deduped, all without a headless browser to maintain. It is free to start with 200 signup credits and no credit card, which is enough to run a real city search and judge the email coverage for your own industry.

Open the API docs, review the integrations, check the pricing, and run your first city-wide email extraction today.

Frequently asked questions

How do I extract emails from a website for free?
For a single site, open the page source with Ctrl+U and search for mailto: and the @ symbol, then check the contact and impressum pages. For many sites, a regex pass over fetched HTML or a free-tier business data API extracts addresses without paid tools. biz collect is free to start with 200 signup credits and no card.
Is it legal to scrape emails from websites?
Scraping publicly visible business contact data is treated differently across jurisdictions, and outreach to those addresses is regulated by laws such as the GDPR, UK GDPR, Swiss FADP, and CAN-SPAM. B2B contact often has a lawful basis, but consent, suppression, and opt-out rules commonly apply. This is not legal advice; confirm the rules for your jurisdiction before sending.
Why can't a tool find every email on a site?
Some businesses publish only a contact form, some render their address as an image, and some assemble it with JavaScript to defeat scrapers. None of those are readable text, so no extractor can recover them. Treat email coverage as partial and keep the phone and website for those records.
What is the best way to extract emails from many websites at once?
For a known list of URLs, a Python script that follows contact and impressum pages and dedupes the results works well. If you also need to find the businesses first, a business data API that combines live local search with on-domain email extraction removes both the discovery scraper and the enrichment scraper.
Should I email scraped addresses immediately?
No. Verify each address first to confirm the mailbox and domain accept mail, filter out role and spam-trap-adjacent addresses, and warm up a cold sending domain gradually. Sending a raw scraped list from a cold domain spikes bounce rates and can get the domain blocked.
Does biz collect rank on-domain emails over free-provider ones?
Yes. An address on the business's own domain is ranked above a generic Gmail or Outlook address, because the on-domain inbox is far more likely to be the real business mailbox. The extractor also follows contact and impressum pages and dedupes the results before returning them.

Turn the article into an API call.

Use biz collect free: 200 signup credits, no credit card, and a clean JSON contract your agent or workflow can call today.

No credit card required200 signup credits20 daily login credits