Skip to main content

Extract URLs & Emails API

Written by Kadri - RichAPI Support Team

POST /extract_urls_emails • Credits: 0.5 credits per call

Extract URLs & Emails scans a block of text and returns every URL and every email address in that text. The response holds a separate urls array and a separate emails array, plus counts and comma-joined strings. Each call costs 0.5 credits ($0.01).

What does Extract URLs & Emails do?

Extract URLs & Emails is a text parser. It takes text that you already hold, such as an email body, a CRM note, or a scraped page fragment. The endpoint runs two regular expressions over that text. One pattern matches email addresses, and one pattern matches URLs. Extract URLs & Emails fetches no page and calls no external provider, so the result depends only on the text in the request body. The endpoint removes duplicate matches and drops a URL that points at a private network address or that carries a cross-site scripting pattern.

Which endpoint does Extract URLs & Emails use?

  • Method: POST

  • URL: https://api.richapi.ai/api/v1/extract_urls_emails

  • Authentication: x-api-key header

  • Response: Synchronous JSON

  • Credits: 0.5 credits per call

  • Success status: 200

How to send an Extract URLs & Emails request

  1. Copy your API key from the RichAPI dashboard.

  2. Put the text to scan in the text parameter.

  3. Send a POST request to https://api.richapi.ai/api/v1/extract_urls_emails.

  4. Send the API key in the x-api-key header.

  5. Read the urls array and the emails array from the response.

CAUTION: Each Extract URLs & Emails call costs 0.5 credits. A call that finds no URL and no email address also costs 0.5 credits.

cURL

curl -X POST https://api.richapi.ai/api/v1/extract_urls_emails   
-H "x-api-key: YOUR_API_KEY"
-H "Content-Type: application/json"
-d '{
"text": "Contact us at [email protected] or visit https://acme.com/pricing"
}'

Python

import requests

response = requests.post(
"https://api.richapi.ai/api/v1/extract_urls_emails",
headers={"x-api-key": "YOUR_API_KEY"},
json={
"text": "Contact us at [email protected] or visit https://acme.com/pricing",
},
timeout=60,
)
response.raise_for_status()
print(response.json())

Node.js

const response = await fetch("https://api.richapi.ai/api/v1/extract_urls_emails", {
method: "POST",
headers: {
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
text: "Contact us at [email protected] or visit https://acme.com/pricing",
}),
});

const data = await response.json();
console.log(data);

Which parameters does Extract URLs & Emails accept?

Parameter

Type

Required

Default

Description

text

string

Yes

""

The text to scan for URLs and email addresses. The maximum length is 10,485,760 characters (10 MB). The stored default is an empty string, and the endpoint rejects an empty string with 400. Always send a real value.

Extract URLs & Emails accepts one parameter. It accepts no query parameter and no path parameter.

What does Extract URLs & Emails return?

The block below is an example response for the request body {"text": "Contact us at [email protected] or visit https://acme.com/pricing"}.

{
"urls": [
"acme.com",
"https://acme.com/pricing"
],
"emails": [
"[email protected]"
],
"url_count": 2,
"email_count": 1,
"total_count": 3,
"urls_and_emails": [
"acme.com",
"https://acme.com/pricing",
"[email protected]"
],
"urls_string": "acme.com, https://acme.com/pricing",
"emails_string": "[email protected]"
}

The urls array holds acme.com because the URL pattern also matches the host name inside [email protected]. The section "What does Extract URLs & Emails pull out of an email signature?" explains that behavior.

Which fields does the Extract URLs & Emails response hold?

Field

Type

Description

urls

array of strings

Every unique URL in the text, in order of first appearance.

emails

array of strings

Every unique email address in the text, in order of first appearance.

url_count

integer

The number of items in the urls array.

email_count

integer

The number of items in the emails array.

total_count

integer

The value of url_count plus the value of email_count.

urls_and_emails

array of strings

One flat list. It holds the whole urls array first, then the whole emails array.

urls_string

string

The urls array joined with a comma and a space. When no URL matched, the value is an empty string.

emails_string

string

The emails array joined with a comma and a space. When no email address matched, the value is an empty string.

Extract URLs & Emails returns this flat object, with no data envelope. Like every RichAPI response, it also carries richapi_meta with the request ID and the credits charged and remaining.

What does Extract URLs & Emails pull out of an email signature?

An email signature is the common case for this endpoint. The text below is a messy signature block. It holds a personal address, two role addresses in different letter case, two full URLs, and one bare host name.

Thanks again for the call.

--
Sarah Chen | VP Marketing, Acme Analytics
[email protected] | +1 415 555 0142
Pricing: https://acme.com/pricing
Book a call: https://calendly.com/sarah-chen/30min
Press enquiries: [email protected]
Media kit: [email protected]
LinkedIn: www.linkedin.com/company/acme-analytics

Send that block as one JSON string. The request body below carries the same text with \n for each line break.

curl -X POST https://api.richapi.ai/api/v1/extract_urls_emails   
-H "x-api-key: YOUR_API_KEY"
-H "Content-Type: application/json"
-d '{
"text": "Thanks again for the call.\n\n--\nSarah Chen | VP Marketing, Acme Analytics\[email protected] | +1 415 555 0142\nPricing: https://acme.com/pricing\nBook a call: https://calendly.com/sarah-chen/30min\nPress enquiries: [email protected]\nMedia kit: [email protected]\nLinkedIn: www.linkedin.com/company/acme-analytics"
}'

The response for that request body is the example below.

{
"urls": [
"sarah.chen",
"acme.com",
"https://acme.com/pricing",
"https://calendly.com/sarah-chen/30min",
"www.linkedin.com/company/acme-analytics"
],
"emails": [
"[email protected]",
"[email protected]"
],
"url_count": 5,
"email_count": 2,
"total_count": 7,
"urls_and_emails": [
"sarah.chen",
"acme.com",
"https://acme.com/pricing",
"https://calendly.com/sarah-chen/30min",
"www.linkedin.com/company/acme-analytics",
"[email protected]",
"[email protected]"
],
"urls_string": "sarah.chen, acme.com, https://acme.com/pricing, https://calendly.com/sarah-chen/30min, www.linkedin.com/company/acme-analytics",
"emails_string": "[email protected], [email protected]"
}

The table below maps each part of the signature to the result.

Part of the text

What Extract URLs & Emails returns

[email protected] in emails. The same address also adds sarah.chen and acme.com to urls.

+1 415 555 0142

Nothing. Extract URLs & Emails matches no phone number.

https://acme.com/pricing

https://acme.com/pricing in urls.

https://calendly.com/sarah-chen/30min

https://calendly.com/sarah-chen/30min in urls.

One entry, [email protected]. The second address is a duplicate in lower case.

www.linkedin.com/company/acme-analytics

The same string in urls. A host name with no scheme matches.

Sarah Chen, VP Marketing, Acme Analytics

Nothing. Extract URLs & Emails matches no name and no job title.

CAUTION: An email address also adds entries to the urls array. The URL pattern matches the host name after the @ sign. It also matches a local part that holds a dot. Filter the urls array against the emails array before you store the result.

The two snippets below remove those entries. Each snippet reads the response object data from the code sample above.

domains = {e.split("@")[-1].lower() for e in data["emails"]}
locals_ = {e.split("@")[0].lower() for e in data["emails"]}
clean_urls = [u for u in data["urls"] if u.lower() not in domains | locals_]

const parts = new Set(data.emails.flatMap((e) => e.toLowerCase().split("@")));
const cleanUrls = data.urls.filter((u) => !parts.has(u.toLowerCase()));

How does Extract URLs & Emails deduplicate and order the results?

Extract URLs & Emails compares every match in lower case. The first form in the text wins, and the response keeps the original letter case of that first form. [email protected] before [email protected] therefore returns [email protected] alone. Both arrays keep the order of first appearance in the text. Extract URLs & Emails sorts nothing and reorders nothing. The urls_and_emails array holds the whole urls array first, then the whole emails array.

Which URLs does Extract URLs & Emails drop?

Extract URLs & Emails removes an unsafe or invalid URL candidate before it builds the urls array. A dropped candidate appears in no field of the response.

Candidate

Reason for the drop

http://localhost:3000/admin

The string holds a loopback host name.

http://127.0.0.1/status

The string holds a loopback address. 0.0.0.0 and ::1 are also dropped.

http://192.168.1.10/admin

The host is a bare IP address. Every bare IP address is dropped.

javascript:alert(1)

The scheme is dangerous. data:, vbscript:, file:, mhtml:, jar:, gopher: and dict: are also dropped.

https://acme.com/?x=document.cookie

The URL holds a cross-site scripting pattern, such as <script, onerror=, onload=, eval(, alert( or document.

https://xn--80ak6aa92e.com

The host is punycode.

https://acme.com/%25foo

The URL is over-encoded. The same rule drops a URL with %00 and a URL with more than 10 percent signs.

https://acme.c/path

The top-level domain is invalid. A top-level domain must hold 2 or more alphanumeric characters.

The filter protects your systems against server-side request forgery and cross-site scripting. The emails array passes through no such filter.

How is Extract URLs & Emails different from Website Email Extractor?

Extract URLs & Emails parses text. Website Email Extractor fetches a live page. Extract URLs & Emails takes text that you already hold, and it returns the URLs and the email addresses inside that text. Website Email Extractor takes one website URL, crawls up to 10 pages of that website, and returns the addresses that the website publishes.

Item

Extract URLs & Emails

Website Email Extractor

Input

A block of text

A website URL

Network activity

None. The endpoint fetches no page.

A live crawl of up to 10 pages

Email output

An emails array of plain strings

One list of objects with a source page, a type and a confidence

URL output

A urls array

None

Credits

0.5 per call

2 per call

To read a live website, send a Website Email Extractor request. To parse text that you already hold, send an Extract URLs & Emails request. A common pattern combines the two: scrape a page with the Web Scraper endpoint, then send the returned text to Extract URLs & Emails.

How much does Extract URLs & Emails cost?

Extract URLs & Emails costs 0.5 credits per call. At $0.02 a credit, the rate on the 1,000 and 5,000 credit packs, one call costs $0.01. Larger packs cost less per credit. The credit count does not change with the length of the text and does not change with the number of matches. RichAPI charges the credits on a 200 response only.

Calls

Credits

Cost

1

0.5

$0.01

100

50

$1.00

1,000

500

$10.00

10,000

5,000

$100.00

100,000

50,000

$1,000.00

Which errors can Extract URLs & Emails return?

Every error response holds an error field with a text message.

Status

Meaning

What to do

400

The request body is not valid JSON, is not a JSON object, holds no text field, holds an empty text value, or holds a text value above 10 MB.

Send a JSON object with a text string that holds at least one non-space character.

401

The API key is missing, wrong or revoked.

Send a valid key in the x-api-key header.

403

This API key has no access to this endpoint (Endpoint not available on your plan).

Call GET /api/v1/my-endpoints to see the endpoints that this key can use. Contact support for access.

404

The endpoint name is wrong.

Send the request to /extract_urls_emails.

405

The request used a method other than POST.

Send the request with the POST method.

429

The request rate is over the limit.

Wait, then send the request again. For a higher limit, contact support.

500

The API failed.

Send the request again. If the failure repeats, contact support.

RichAPI charges no credit for a 400, 401, 403, 404, 405, 429 or 500 response.

Frequently asked questions

Does Extract URLs & Emails fetch the URLs that it finds?

No. Extract URLs & Emails sends no HTTP request and opens no page. It reads only the text in the request body. A URL in the urls array is a string match, not a confirmed live page.

Does Extract URLs & Emails return the same address two times?

No. The urls array and the emails array hold each match one time. The comparison runs in lower case, and the first form in the text wins, so [email protected] and [email protected] return one entry.

Why does the urls array hold the domain of an email address?

The URL pattern matches a bare host name, and every email address holds a host name after the @ sign. The pattern also matches a local part that holds a dot, as in [email protected]. Filter the urls array against the emails array to remove those entries.

Does a call that finds no URL and no email address cost credits?

Yes. Every 200 response costs 0.5 credits, and an empty result is a 200 response with total_count set to 0. RichAPI charges no credit for a 4xx error and no credit for a 5xx error.

Why does a URL in the response end with a full stop or a comma?

The URL pattern stops at a space character, at a line break, and at the characters <, >, " and '. It stops at no other punctuation. The text visit https://acme.com/pricing. therefore returns https://acme.com/pricing. with the full stop. Trim the trailing punctuation in your own code.

How much text can one Extract URLs & Emails call hold?

One call holds up to 10,485,760 characters (10 MB) in the text parameter. A longer value returns 400 and costs no credit.

Does Extract URLs & Emails find phone numbers?

No. Extract URLs & Emails matches URLs and email addresses only. To parse a phone number, send the number to the /normalize_phone endpoint, which also costs 0.5 credits per call.

Related articles

Did this answer your question?