Email Extractor from Text: Emails, Phones & URLs from Any Text
Pricing
from $0.12 / 1,000 item extracteds
Email Extractor from Text: Emails, Phones & URLs from Any Text
Email extractor from text: extract email addresses, phone numbers (E.164), URLs, domains and social handles from pasted text, PDF, DOCX, XLSX, CSV, HTML and EML files or datasets. Finds obfuscated emails like name [at] domain [dot] com. Syntax check only, nothing is sent.
Pricing
from $0.12 / 1,000 item extracteds
Rating
0.0
(0)
Developer
Data Done Right
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Security
Limited permissionsShare
This email extractor from text pulls email addresses, phone numbers (E.164), URLs, domains and social handles out of text you already have: pasted text, PDF, Word, Excel, CSV, HTML and email files (EML, MSG), or a text field of an Apify dataset. It also finds emails that people hide from bots, such as jane.doe [at] acme [dot] com. Use it to extract emails from text, to extract email addresses from a document, or as a quick email extractor for a pile of notes. It reads only what you give it: it does not crawl websites, send email or check mailboxes.
What you get:
- One row per unique item: type, original value, normalised value (lowercase email, E.164 phone, clean URL), domain, count, source and a context snippet.
- A per-source report (what was found in each text or file, and why a file failed) and a run summary.
- Pay per item extracted, nothing else. Sources that fail or return nothing cost nothing.
To extract emails from websites instead of text you already have, use Domain List Email Extractor: Emails & Phones from Websites (see Related tools).
Privacy and responsible use
You supply the text, files and datasets. Only process data you are allowed to process, and follow the rules that apply to you (GDPR, CAN-SPAM, PECR and the terms of the source). This Actor does not send email, does not contact the addresses it finds, does no SMTP probing and no MX lookup. Email addresses are checked for syntax only. IBAN extraction is off by default because bank numbers are sensitive. Downloaded files are read in memory/temporary storage and deleted at the end of the run. The Actor never logs in anywhere, and refuses login-walled social sites and internal addresses.
What can it extract
| Type | What you get | Normalised as |
|---|---|---|
email | RFC-practical syntax, plus name [at] domain [dot] com, name(at)domain.com, name at domain dot com, @, %40, mailto: links, zero-width characters. isRole flags info@, sales@, noreply@ and similar. obfuscated says whether it was hidden. | lowercase local@domain |
phone | Numbers valid for their country (libphonenumber), with country, national and international format and line type | E.164, for example +14155552671 |
url | http://, https:// and www. links, with trailing punctuation removed | lowercase host, no fragment, no default port |
domain (option) | Domains of the emails and URLs that were found | bare domain, no www. |
social and handle (option) | Profile links on X/Twitter, Instagram, Facebook, LinkedIn, TikTok, YouTube, GitHub, Telegram, Threads, Pinterest, and plain @mentions | platform:handle or @handle |
iban (option, off by default) | IBANs that pass the country length and mod-97 checksum | compact IBAN |
How to extract emails from text
- Open the Actor and paste your text into Texts to scan. Each entry is one source (an entry can be a whole email thread).
- Leave Extract emails, Extract phone numbers and Extract URLs on, or switch on domains, social handles or IBANs.
- Run it, then download the dataset as JSON, CSV, Excel or HTML. Filter on the
typecolumn to get only emails.
How to extract email addresses from a PDF, Word or Excel file
Put the public links in File URLs: PDF, DOCX, XLSX, CSV, TXT, HTML, EML or MSG. The Actor downloads each file (up to the size limit), reads its text including table cells, headers and footers, and the links hidden behind words (mailto: links in PDFs, Word and HTML are read too). Scanned PDFs without a text layer need OCR first; this Actor does not do OCR and tells you so in the source report.
How to find obfuscated emails like name [at] domain [dot] com
Nothing to configure: de-obfuscation is always on. jane.doe [at] acme [dot] com, jane(at)acme.com, jane{at}acme{dot}org, anna DOT smith AT corp DOT de and sam@adatum.net come out as normal addresses with details.obfuscated: true. A bare at is only decoded when the domain also uses a spelled-out dot, so ordinary sentences such as "meet me at noon.com" are left alone.
How to extract emails from a dataset of another Actor
Pick the Dataset and set Dataset field (default text; dotted paths such as contact.notes work, and lists of strings are joined). Every dataset item becomes one source, so each row tells you which item it came from.
Input
Copy-paste input (this is the prefill):
{"texts": ["Contact our sales team at sales@acme-example.com or call +1 415 555 2671. For support write to support@acme-example.com (office hours 9-5) or phone +44 20 7946 0958. Our CEO Jane Doe can be reached at jane.doe [at] acme-example [dot] com, and press questions go to Press.Team@Acme-Example.com. More info: https://www.acme-example.com/contact"]}
| Field | Default | What it does |
|---|---|---|
texts | prefill | Texts to scan, one source per entry |
fileUrls | empty | Public links to PDF, DOCX, XLSX, CSV, TXT, HTML, EML, MSG files |
datasetId, datasetField | empty, text | Scan a field of every item of an Apify dataset |
extractEmails | true | Email addresses |
extractPhones | true | Phone numbers in E.164 |
extractUrls | true | Web links |
extractDomains | false | Domains of found emails and URLs |
extractSocialHandles | false | Social profile links and @mentions |
extractIbans | false | IBANs that pass the checksum |
defaultRegion | US | 2-letter country for phone numbers without a + prefix (empty: only + numbers) |
dedupe | global | global one row per unique item across sources, perSource, or off (every occurrence) |
lowercaseEmails | true | Lowercase the normalised email |
skipRoleAccounts | false | Drop info@, sales@, support@, admin@, noreply@ and similar |
domainAllowList | empty | Keep only emails and URLs on these domains (subdomains included) |
domainDenyList | empty | Drop emails and URLs on these domains |
contextChars | 60 | Characters of surrounding text on each side (0 switches it off) |
maxItems | 1000 | Maximum rows returned and charged |
maxSources | 1000 | Maximum texts, files and dataset items read |
maxFileSizeMb | 25 | Larger files are skipped and reported |
maxPdfPages | 200 | Pages read per PDF |
maxCharsPerSource | 2,000,000 | Longer texts are cut, and the cut is reported |
concurrency, timeoutSecs | 4, 30 | File download parallelism and timeout |
proxyConfiguration | none | Optional, only for file URLs |
Output
One dataset row per item. Real output of the prefill run (shortened to two rows):
[{"index": 3,"type": "email","value": "jane.doe@acme-example.com","normalised": "jane.doe@acme-example.com","domain": "acme-example.com","count": 1,"source": "text 1","sourceType": "text","sourceCount": 1,"sources": ["text 1"],"context": "...phone +44 20 7946 0958. Our CEO Jane Doe can be reached at jane.doe@acme-example.com, and press questions go to Press.Team@Acme-Example.com. Mor...","details": {"localPart": "jane.doe", "tld": "com", "isRole": false, "syntaxValid": true, "obfuscated": true}},{"index": 6,"type": "phone","value": "+44 20 7946 0958","normalised": "+442079460958","domain": null,"count": 1,"source": "text 1","sourceType": "text","sourceCount": 1,"sources": ["text 1"],"context": "...ite to support@acme-example.com (office hours 9-5) or phone +44 20 7946 0958. Our CEO Jane Doe can be reached at jane.doe@acme-example.c...","details": {"region": "GB", "countryCode": 44, "national": "020 7946 0958", "international": "+44 20 7946 0958", "numberType": "FIXED_LINE"}}]
Rows are ordered emails first, then phones, URLs, social handles, domains and IBANs, in order of first appearance. The context snippet shows the text after de-obfuscation.
Two key-value store records come with every run:
SUMMARY: totals by type, items returned and charged, filtered counts, notes about anything that went wrong.SOURCES: one entry per text, file or dataset item with its status, file type, number of unique items found by type, and the error if it failed (for exampledownload failed: HTTP 404).
How much does it cost
Pay per event: item-extracted = $0.00015 per output row ($0.15 per 1,000 rows). Sources that fail, are empty or are skipped produce no rows and cost nothing. maxItems caps both the rows and the cost.
| Example | Rows | Price |
|---|---|---|
| 250 short texts with about 4 items each | 1,000 | about $0.15 |
| A 300-page PDF directory with 10,000 unique emails and phones | 10,000 | about $1.50 |
| A scraper dataset of 20,000 items with 100,000 unique contacts | 100,000 | about $15 |
Apify platform usage (compute) is included in the event price. With dedupe global you only pay for unique items, not for repeats.
Use cases
- Clean a mailbox export, support thread or meeting notes into a contact list.
- Pull the email addresses and phone numbers out of a PDF directory, a conference attendee list or a Word proposal.
- Read the output of another scraper (a
descriptionorbiofield) and add emails and handles to it. - Decode the "name [at] domain [dot] com" addresses on a copied staff page, then filter to the company domain.
- Normalise phone numbers from mixed national formats to E.164 before importing into a CRM.
FAQ
Does it verify that an email address exists? No. It checks syntax only. There is no MX lookup, no SMTP probing and nothing is ever sent, so a syntactically valid address may still bounce. Run a dedicated verifier before a campaign.
Does it crawl websites? No. It parses text and files you give it. A file URL pointing to an HTML page is downloaded once and parsed as a document, with no links followed and no JavaScript run. To crawl company websites, use Domain List Email Extractor.
How does it decide a phone number is real?
It uses Google's libphonenumber rules and keeps only numbers that are valid for their country. Numbers without a + prefix are read with defaultRegion. Long IDs, dates and order numbers are mostly ignored, but a digit string that happens to look like a valid number can still be returned; check the region and numberType fields.
Which files can it read, and what can it not read?
PDF (text layer only, no OCR), DOCX, XLSX (values, not formulas), CSV/TXT and other text, HTML, EML and MSG. It does not unpack ZIP archives, read legacy .doc/.xls files or password-protected PDFs, and it does not read images. Failed files are listed in SOURCES with the reason.
Are role accounts and free-mail addresses flagged?
Role accounts (info@, sales@, noreply@ and about 60 more) get isRole: true and can be skipped with skipRoleAccounts. Free-mail providers are not flagged; use domainDenyList with gmail.com and similar to drop them.
Is my text stored or sent anywhere? No third-party service is called. The text is processed inside the Actor run; items are written to your own dataset. File URLs are downloaded from the public internet from the Actor, and internal and private addresses are blocked.
Limits
- Syntax check only for emails (see above). IBANs only for the countries in the IBAN registry list built in.
- Names are not extracted; a row is an address, number or link, with the surrounding text in
context. - Cut-offs are reported:
maxCharsPerSourcefor long texts,maxPdfPages,maxFileSizeMb,maxItems,maxSources. - With dedupe
global,sourceis the first source andsourceslists at most 25 sources (sourceCounthas the real number).
Use with the Apify API, MCP, n8n and Make
Run it from any tool that can call the Apify API. In n8n use the Apify node (Run Actor, then Get Dataset Items), in Make use the Apify app, and for AI agents use the Apify MCP server, which exposes this Actor with its input schema.
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("<your-username>/email-extractor-from-text").call(run_input={"texts": ["Write to jane.doe [at] acme-example [dot] com or call +1 415 555 2671"],"skipRoleAccounts": True,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["type"], item["normalised"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('<your-username>/email-extractor-from-text').call({fileUrls: ['https://example.com/contacts.pdf'],extractDomains: true,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.map((i) => `${i.type} ${i.normalised}`));
Related tools
- Domain List Email Extractor: Emails & Phones from Websites to find contact details by crawling company websites.
- Phone Number Validation & Lookup: Format, Carrier, Line Type to check and enrich the phone numbers you extracted.
- Merge Datasets & Dedupe: Combine, Filter, Export CSV & Excel to merge the extracted rows with other datasets and remove duplicates.