The problem: finding emails in unstructured text is harder than it looks
You have a document — a contact list, a web page, a log file, a CSV export, a pile of forwarded emails — and you need every email address out of it. The instinct is to search for the @ symbol and grab the text around it. That works for clean input. It fails on real-world input.
Real text contains obfuscated emails (bob [at] example [dot] com), HTML-encoded emails (<a href="mailto:info@site.com">), CSV-quoted emails ("john@csvdata.com"), duplicate emails appearing 15 times in a mailing list, malformed addresses (user@.com, @domain.com, user@domain), and emails mixed with URLs, phone numbers, and IP addresses that you may or may not also want to collect. A simple find-the-@ approach returns garbage alongside the good data.
The Email Extractor handles this with regex-based extraction, input format detection (plain text, HTML, CSV), obfuscation deobfuscation, email validation, deduplication with occurrence counting, domain grouping, and filtering by domain, TLD, or custom regex. It also extracts URLs, phone numbers, and IP addresses simultaneously — the same text often contains all four.
Fastest path
Open the Email Extractor, paste your text into the input area (or upload a file — .txt, .csv, .html, .log, .json, .xml are accepted), and the tool extracts emails automatically. Toggle which data types to extract (emails, URLs, phone numbers, IP addresses) using the buttons at the top. The format selector defaults to auto-detect — if you paste HTML, it strips tags and extracts mailto: addresses. If you paste CSV, it handles delimiters. Adjust options (remove duplicates, lowercase, detect obfuscated, validate emails) as needed. Filter by domain, TLD, or custom regex pattern. Copy results, export as TXT/CSV/JSON, or save to history (stored locally in your browser).
The email regex: what each part matches
The tool extracts emails with this pattern:
/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g
Broken down:
[a-zA-Z0-9._%+-]+— the local part (before the @). Matches one or more letters, digits, dots, underscores, percent signs, plus signs, or hyphens. This covers most legal email local parts but is permissive — it matches..user(leading dots, which are invalid) anduser--name(consecutive hyphens, which some providers reject). The regex prioritizes recall (catch everything that looks like an email) over precision (only catch valid emails). Validation happens separately.@— the literal @ symbol. No ambiguity here.[a-zA-Z0-9.-]+— the domain name. Letters, digits, dots, and hyphens. This matchesexample.com,sub.example.co.uk,my-domain.org. It also matches invalid domains likeexample..com(consecutive dots) and-example.com(leading hyphen).\.[a-zA-Z]{2,}— the TLD. A literal dot followed by two or more letters. The 2-letter minimum filters out things likeuser@domain.(no TLD) anduser@domain.c(single-letter TLD, which does not exist). It does not validate whether the TLD is real —user@domain.zzmatches even though.zzis not a registered TLD. The ICANN root zone has roughly 1,500 TLDs; the regex does not check against that list.
The g flag makes the regex global — it finds all matches in the text, not just the first. Without g, you get one email per text. With g, you get every email in the document.
Why extraction and validation are different
The extraction regex is permissive. It catches user@domain..com (double dot), user@-domain.com (leading hyphen in domain), and ..test@gmail.com (leading dots in local part). These are syntactically wrong but match the pattern because the character classes are broad.
The tool has a separate validation function that checks each extracted email against a stricter pattern:
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*\.[a-zA-Z]{2,}$/
This pattern enforces:
- Domain labels cannot start or end with a hyphen (
[a-zA-Z0-9]at start,[a-zA-Z0-9]at end, hyphens only in the middle) - The TLD must be at least 2 letters
- The entire string must match (
^and$anchors), not just a substring
The validation regex is closer to RFC 5322 compliance but still not complete. RFC 5322 allows quoted local parts ("user name"@domain.com), comments in parentheses, and internationalized characters (UTF-8) in domains (IDN). The tool's regex does not handle these — they are rare and complex, and supporting them introduces false positives from text that happens to contain quotes and parentheses.
The tool marks each extracted email as valid or invalid based on this second regex. You can filter to show only valid emails, or keep both to inspect what the extraction caught that validation rejected.
Obfuscated emails: why people hide them and how to find them
Email addresses on web pages get scraped by bots. To slow this down, people obfuscate them — replacing @ with [at] and . with [dot]. A contact page that says "Email me at bob [at] example [dot] com" is readable by humans but invisible to a simple email regex. The pattern looks for a literal @ between the local part and domain, and [at] is not @.
The tool handles three obfuscation formats before running the extraction regex:
Bracketed: user [at] domain [dot] com and user (at) domain (dot) com
/([a-zA-Z0-9._%+-]+)\s*[\[\(]\s*at\s*[\]\)]\s*([a-zA-Z0-9.-]+)\s*[\[\(]\s*dot\s*[\]\)]\s*([a-zA-Z]{2,})/gi
This matches square brackets [at] and parentheses (at), with optional whitespace, case-insensitive. The replacement reconstructs the email as $1@$2.$3.
Braced: user {at} domain {dot} com
/([a-zA-Z0-9._%+-]+)\s*\{at\}\s*([a-zA-Z0-9.-]+)\s*\{dot\}\s*([a-zA-Z]{2,})/gi
Curly braces are less common but appear in some forum software and wiki templates.
Word form: user AT domain DOT com
/([a-zA-Z0-9._%+-]+)\s+AT\s+([a-zA-Z0-9.-]+)\s+DOT\s+([a-zA-Z]{2,})/g
This matches uppercase AT and DOT as standalone words (surrounded by whitespace). It is case-sensitive on purpose — lowercase "at" and "dot" appear too often in normal English to be reliable obfuscation markers.
Deobfuscation runs as a preprocessing step. The tool converts obfuscated forms to standard email format, then runs the extraction regex on the converted text. Emails found only after deobfuscation are tagged with a "deobfuscated" badge so you know they were hidden in the source. The tool also shows a count of deobfuscated emails in the stats panel.
Input format detection and preprocessing
The tool auto-detects three input formats and preprocesses each differently:
HTML is detected by the presence of tags (<[a-z]...> with closing tags or self-closing syntax). The tool strips <script> and <style> blocks (which contain JavaScript and CSS, not email content), extracts mailto: links from href attributes (converting href="mailto:info@site.com" to info@site.com), strips all remaining HTML tags, and decodes HTML entities (& → &, < → <, → space). Without this preprocessing, the extraction regex would match email addresses inside HTML attributes and JavaScript, producing noise.
CSV is detected by counting comma-separated fields across the first 5 lines. If 2 or more lines have 2+ commas, the input is treated as CSV. The tool replaces delimiters (commas, semicolons, pipes, tabs, quotes) with spaces, converting structured CSV into flat text that the extraction regex can scan. This is lossy — the column structure is discarded — but sufficient for email extraction, where you want the addresses regardless of which column they were in.
Plain text requires no preprocessing. The extraction regex runs directly on the input.
You can override auto-detection by manually selecting the format. If you know your input is HTML but the auto-detect fails (common for HTML fragments without closing tags), select HTML explicitly.
Filtering: domain, TLD, and custom regex
After extraction, the tool offers four filters:
Include domains — comma-separated list. Only emails from matching domains are kept. gmail.com, yahoo.com shows only Gmail and Yahoo addresses. The match is a substring check, so company.com matches both user@company.com and user@sub.company.com.
Exclude domains — the inverse. spam.com, temp-mail.org removes addresses from those domains. Useful for filtering disposable email providers from a contact list.
TLD filter — comma-separated TLD list. com, org, io shows only addresses ending in those TLDs. The TLD is extracted as the part after the last dot in the domain. Clicking a TLD badge in the TLD distribution panel applies this filter automatically.
Custom regex — a JavaScript regex pattern applied to each email address. .*@company\.com$ matches any address at company.com. The pattern is case-insensitive and applied to the normalized (lowercased) email. If the pattern is invalid JavaScript regex, the filter is skipped silently — no error, no results.
Deduplication and occurrence counting
Email lists from real-world sources contain duplicates. A mailing list export might have the same address 10 times across different entries. A web page might list support@company.com in the header, footer, and contact section.
The tool deduplicates by default, keeping one instance of each unique address. But it also counts occurrences — how many times each address appeared in the source text before deduplication. The occurrence count is shown as a badge (x3) next to each email in the results. This tells you which addresses are most prominent in the source, which is useful for identifying primary contacts versus one-off mentions.
Deduplication is case-insensitive when the lowercase option is enabled (default). John@Gmail.com and john@gmail.com are treated as the same address. With lowercase disabled, they are treated as different — which is technically incorrect, since the domain part of an email is case-insensitive per RFC 5321, and most providers treat the local part as case-insensitive too.
Beyond emails: URLs, phones, and IPs
The tool extracts four data types simultaneously from the same input:
URLs: /https?:\/\/[^\s<>"{}|\\^[]]+/gi— matcheshttp://andhttps:// followed by any non-whitespace, non-delimiter characters. It catches full URLs including paths and query strings. It does not match protocol-relative URLs (//example.com) or bare domains (example.com` without a protocol).
Phone numbers: /(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}/g — matches US/North American phone number formats: optional country code (+1), optional area code in parentheses, three-digit prefix, four-digit line number, with various separator styles. Results are filtered to 7+ digits to eliminate false positives from short digit sequences. International phone formats are not supported.
IP addresses (IPv4): Matches four octets (0-255) separated by dots, with proper validation that rejects numbers above 255. 192.168.1.1 matches. 256.1.1.1 does not. IPv6 is not supported.
Gotchas
- The extraction regex catches invalid emails.
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}matchesuser@domain..com(double dot),user@-domain.com(leading hyphen), and..test@gmail.com(leading dots). The validation regex flags these as invalid, but they still appear in the results unless you enable "Show only valid." If you need only RFC-compliant addresses, turn on validation and filter to valid only. - Deobfuscation is heuristic, not perfect. The three obfuscation patterns cover common formats but miss others.
user at domain dot com(lowercase, no brackets) is not caught — the word-form regex requires uppercase AT and DOT to avoid false positives on normal English.user{at}domain{dot}com(no spaces) is not caught — the braced pattern requires whitespace.u s e r @ d o m a i n . c o m(spaced characters) is not caught by any pattern. If the source uses an unusual obfuscation style, manual cleanup is needed. - CSV preprocessing is lossy. The tool replaces all delimiters with spaces, which means a CSV cell containing
john,doe@gmail.com(a comma inside a cell) produces two extracted items:john(not an email, discarded) anddoe@gmail.com. But a properly quoted cell"john,doe@gmail.com"becomesjohn doe@gmail.comafter quote stripping and delimiter replacement — the regex seesdoe@gmail.comand extracts it, but the local part is actuallyjohn,doe. For CSV files where emails may contain commas in quoted fields, the extraction may split addresses incorrectly. - Phone number extraction is US-only. The regex matches North American Numbering Plan format (country code +1, 3-digit area code, 3-digit prefix, 4-digit line). UK (+44), German (+49), Indian (+91), and other international formats are not matched. A UK number like
+44 20 7946 0958produces no match. If your source text contains international phone numbers, they will not be extracted. - Large file processing blocks the UI. The tool chunks input at 50,000 characters and yields to the UI thread between chunks, showing a progress bar. But the extraction regex itself runs synchronously on the full input after chunking — a 10 MB text file with thousands of emails can freeze the tab for several seconds during the regex match. For very large files (over 5 MB), consider splitting the file first or using a command-line tool like
grep -oEfor extraction.
Summary
- Email extraction uses the regex
[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}— a permissive pattern that catches most email addresses but also matches invalid ones. Validation uses a stricter regex that enforces RFC-compliant domain label rules. Extraction prioritizes recall (catch everything); validation prioritizes precision (only correct addresses). - Obfuscated emails (user [at] domain [dot] com) are deobfuscated before extraction using three regex patterns for bracketed, braced, and word-form obfuscation. Deobfuscated emails are tagged so you know they were hidden in the source. The patterns are heuristic — unusual obfuscation styles are missed.
- Input format auto-detection handles HTML (tag stripping, mailto: extraction, entity decoding), CSV (delimiter replacement), and plain text. HTML preprocessing prevents the regex from matching email addresses inside script tags and attributes. CSV preprocessing is lossy — column structure is discarded.
- The tool extracts four data types simultaneously: emails, URLs (http/https), phone numbers (US/NANP format only), and IPv4 addresses. Filters include domain include/exclude, TLD filter, and custom regex. Deduplication with occurrence counting shows which addresses appear most frequently in the source.
- Use the Email Extractor for extracting contact data from text, the Regex Tester for building and testing custom extraction patterns, the Word Counter for text statistics, and the Text Compare tool for diffing two versions of a document.