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 extractemails → slugify 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. GitHub • Docs • Changelog