Back to blog
apiextractionemailtext-processing

Extract Emails from Text Without Writing a Regex

Somewhere in your intake pipeline is a string like:

Contact John at john@example.com, CC jane@corp.io. Bounce: sales@x.com (do not reply).

You want the three addresses. So you write a regex. [\w.]+@\w+\.\w+. It misses the subdomain. You add it. Then a +tag address breaks it. Then an international TLD. By the time it handles first.last+work@mail.co.uk you have a 90-character monster that still fails on the next ticket.

One call does it:

curl -s -X POST https://textforge.co/v1/run \
-H "Content-Type: application/json" \
-d '{"input":"Contact John at john@example.com, CC jane@corp.io. Bounce: sales@x.com","pipeline":["extractemails"]}'

Returns:

["john@example.com", "jane@corp.io", "sales@x.com"]

Note the shape: an array, not an object. This is the part that bites people. Every extraction transform (extract-emails, extract-urls, extract-numbers) returns a list. It does not return {"emails": [...]}. If your code does JSON.parse(result).emails, it throws — there is no .emails. You want JSON.parse(result), which is already the array.

The Gotcha: Chaining

Pipelines run each step on the previous step's output. So extractemailsslugify feeds the array into slugify, which expects a string, and you get garbage. Extraction steps are terminal — call each one on its own:

extracturls  -> ["https://example.com", "http://corp.io"]
extractnumbers -> [42, 7]

Use it for: parsing support tickets, scraping contact fields, de-duplicating mailing lists, pulling addresses out of scraped HTML before you sanitize it.

Try It Now

Playground: textforge.co/playground — paste the blob, pick extractemails, see the array.

Docs: textforge.co/docs — all 28 transforms, rate limits.

Free tier: 1,000 requests/day. No key. No signup.


Built this because I was maintaining three regexes that all broke on a Tuesday. Free for 1K/day. GitHubDocsChangelog


Try it free

1,000 requests/day. No API key. No signup.

Open Playground →