Email Extractor
Paste any block of text and pull out every valid, deduplicated email address instantly.
About the Email Extractor
Paste in raw text, page source, or a contact list, and a regex pattern pulls out every email-shaped string, case-insensitively removes repeats, and lists what's left. Nothing gets uploaded; the matching happens right in your browser tab, so you can paste sensitive lists without worry.
Why the pattern doesn't try to match the full email specification
The actual RFC 5322 grammar for what counts as a technically valid email address is famously enormous, it permits quoted local parts with embedded spaces, comments, and character combinations that essentially never appear in real, working addresses anyone actually uses. A regex that fully implements that specification is genuinely hundreds of characters long and mostly matches theoretical edge cases nobody sends mail to. This tool's pattern, [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}, deliberately covers the practical subset instead, letters, digits, and a handful of common punctuation characters before the @ symbol, a domain made of letters, digits, dots, and hyphens, ending in a realistic top-level-domain-shaped suffix. That's the right tradeoff for this tool's actual job: finding genuinely usable email-shaped strings scattered through pasted text, not exhaustively validating every theoretically-permitted edge case of a single known address.
What this simplified pattern won't catch
Being honest about the tradeoff: this pattern won't match a handful of rare but technically valid forms, quoted local parts like "john doe"@example.com, raw IP-address domain literals like user@[192.168.1.1], or internationalized domain names using non-Latin characters. In exchange for skipping those edge cases, it correctly and reliably catches the overwhelming majority of addresses people actually paste in, from page source, exported contact lists, CSV dumps, or plain copied text, which is what this tool is actually built for.
Why deduplication is case-insensitive but the display isn't forced to lowercase
Email domains are case-insensitive by long-standing convention and in practice virtually every real mail server treats them that way, so John@Example.com and john@example.com should be recognized as duplicates of the same address. This tool's deduplication logic does exactly that, it lowercases each match purely to use as an internal comparison key for its Set, while still pushing the original, exactly-as-typed casing into the results list. That means the first version of an address encountered in your pasted text is what displays, duplicates get silently dropped, but nothing gets forcibly rewritten to all-lowercase just because the comparison logic needed a normalized key internally.
How the download button creates a file with no server involved
Clicking Download as .txt builds an in-memory Blob object containing your extracted email list, generates a temporary blob: URL pointing at it with URL.createObjectURL(), creates an invisible link element pointing at that URL with a download attribute (which tells the browser to save the file rather than navigate to it), programmatically clicks that link, then immediately removes it and calls URL.revokeObjectURL() to free the temporary reference. The entire sequence happens locally in memory, there's no server generating or hosting the file, which is the same reason nothing you paste here ever needs to leave your browser tab in the first place.
A practical use case: cleaning up scraped or exported contact data
This kind of extraction is most useful on text that's messy by nature, an exported CRM contact list with extra columns, HTML page source with emails buried inside mailto links and attribute values, or a forwarded email thread where addresses are scattered throughout headers and signatures. Because the regex only cares about the email-shaped pattern itself and ignores everything else surrounding it, you don't need to manually strip out HTML tags, CSV commas, or unrelated text first, pasting the raw, unprocessed source directly and letting the pattern pick out just the addresses is usually faster than trying to clean the input up by hand beforehand.
Frequently Asked Questions
Why doesn't this tool use the "official" full email address specification?
The full RFC 5322 grammar is enormous and mostly matches theoretical edge cases that essentially never appear in real addresses, like quoted local parts with embedded spaces. This tool uses a practical, simplified pattern instead, tuned to reliably catch real-world addresses in pasted text rather than exhaustively validate every technically-permitted form.
What kinds of email addresses might this tool miss?
Rare forms like quoted local parts, raw IP-address domain literals, and internationalized non-Latin domain names aren't matched. In exchange, the simpler pattern reliably catches the overwhelming majority of addresses people actually paste from page source, contact lists, or CSV files.
If the same email appears with different capitalization, will it show up twice?
No, deduplication compares addresses case-insensitively (matching real-world mail server behavior for domains), so John@Example.com and john@example.com are treated as duplicates. The first version encountered in your text is the one kept, it isn't forcibly rewritten to lowercase.
Does clicking Download as .txt upload anything to a server?
No, the file is built entirely in memory using a Blob object and a temporary local blob: URL, then triggered as a browser download via a programmatically clicked link. No server generates or hosts the file at any point.
Is it safe to paste a sensitive contact list into this tool?
Yes, all extraction happens locally in your browser tab using JavaScript regex matching. Nothing you paste is ever transmitted anywhere, which is exactly what makes it safe to use with real, sensitive contact data.
Does the extracted list update as I type or paste?
Yes, extraction re-runs on every input event, so the results, count, and available copy/download actions all update live as you paste or edit the text, with no separate button needed to trigger extraction.