FairqueryBlogToolsAboutSecurityllms.txt

How do I find a company's contact email, phone and social profiles from its domain?

Fairquery ·

Short answer: fetch the company's homepage plus its contact, about and imprint pages (respecting robots.txt), extract mailto:/tel: links, JSON-LD Organization data, obfuscated emails and social links, then validate the emails' domain for MX records. The Fairquery Website Contact & Company Enricher does all of that per domain and returns one clean row (role emails, E.164 phones, socials, company name, description, address) for $0.003 per domain; unreachable, blocked or invalid domains are free.

What you get per domain

How it works

  1. Normalises each input (https://www.Acme.com/contact, jane@acme.com, acme.com → acme.com) and removes duplicates.
  2. Reads robots.txt (RFC 9309) and honours Disallow and Crawl-delay for user agent FairqueryBot.
  3. Fetches the homepage, then the best-scoring same-site pages (contact, Kontakt, contacto, about, imprint/Impressum, legal notice, team) up to maxPagesPerDomain (default 5, max 15), one request at a time per site with requestDelayMs (default 1,000 ms) between them.
  4. Extracts JSON-LD, mailto:/tel: links, Cloudflare-protected emails, name [at] domain [dot] com obfuscation, social links and addresses, then validates the emails.

It is plain HTTP, with no headless browser and no proxy, so sites that render contact details only with JavaScript or block datacenter IPs return fewer fields.

How to run it with curl

curl -X POST \
  "https://api.apify.com/v2/acts/fairquery~website-contact-company-enricher/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domains": ["apify.com"], "maxPagesPerDomain": 4}'

Real output from that request

We ran exactly this on October 17, 2026 (row shown in full, minus the timestamp and the duplicate addresses array):

{
  "type": "domain",
  "input": "apify.com",
  "domain": "apify.com",
  "final_url": "https://apify.com/",
  "company_name": "Apify Technologies s.r.o.",
  "description": "Thousands of tools to automate your business. Get real-time web data, track competitors, generate leads, and integrate your apps and AI agents.",
  "emails": [
    {
      "email": "hello@apify.com",
      "source_url": "https://apify.com/contact",
      "is_role_account": true,
      "on_company_domain": true,
      "is_free_provider": false,
      "is_disposable": false,
      "verdict": "valid",
      "reasons": [
        "ROLE_ACCOUNT"
      ],
      "has_mx": true,
      "mail_provider": "Google Workspace / Gmail"
    }
  ],
  "primary_email": "hello@apify.com",
  "phones": [],
  "social_links": {
    "github": [
      "https://github.com/apify"
    ],
    "linkedin": [
      "https://linkedin.com/company/apify"
    ],
    "twitter": [
      "https://x.com/apify"
    ],
    "tiktok": [
      "https://tiktok.com/@apifytech",
      "https://tiktok.com/@apifyoffice"
    ]
  },
  "address": "Na Příkopě 959/27, 11000, Prague, CZ",
  "mail_domain": {
    "has_mx": true,
    "null_mx": false,
    "mail_provider": "Google Workspace / Gmail",
    "has_spf": null,
    "has_dmarc": null,
    "dmarc_policy": null
  },
  "pages_crawled": [
    "https://apify.com/",
    "https://apify.com/contact",
    "https://apify.com/contact-sales"
  ],
  "pages_blocked_by_robots": 0,
  "robots_txt": "ok",
  "email_scope": "role"
}

The run crawled 3 pages, took 5.1 seconds and would cost $0.003. The README documents about 3–8 seconds per domain with the default politeness settings and 5 domains in parallel, so 100 domains take roughly 1–3 minutes. No phone number was published on the crawled pages here, so phones is empty rather than guessed.

Python: enrich a CSV of company websites

import csv, os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
domains = [row["website"] for row in csv.DictReader(open("companies.csv"))]
run = client.actor("fairquery/website-contact-company-enricher").call(
    run_input={"domains": domains, "emailScope": "role", "defaultPhoneCountry": "US"}
)
for r in client.dataset(run["defaultDatasetId"]).iterate_items():
    if r["type"] == "domain":
        print(r["domain"], r["primary_email"], [p["e164"] for p in r["phones"]],
              r["social_links"].get("linkedin"))
    else:
        print("skipped:", r.get("code"), r.get("message"))

Input options

FieldDefaultMeaning
domains(required)Domains, URLs or emails
maxPagesPerDomain51–15, homepage included
emailScoperolebusiness adds named addresses on the company's own domain; all returns everything found
validateEmailstrueMX / disposable / typo checks
checkSpfDmarcfalseSPF/DMARC for the company mail domain
defaultPhoneCountry–e.g. US; also parses national-format numbers in page text
domainConcurrency / requestDelayMs / requestTimeoutSecs5 / 1000 / 15Politeness and timeouts
maxDomains1000Safety cap per run

Error rows (never charged): INPUT_EMPTY, INVALID_DOMAIN, MAX_DOMAINS_EXCEEDED, SITE_UNREACHABLE, BLOCKED_BY_ROBOTS, ENRICH_FAILED.

From an AI agent

Call Actor fairquery/website-contact-company-enricher through Apify MCP, or run the stdio MCP server from the GitHub repo. It has enrich_domains (paid, your Apify token) and a free local normalize_domains tool for cleaning a messy list first. Real output of normalize_domains for ["https://www.Apify.com/contact", "jane@stripe.com", "basecamp.com", "apify.com", "not a domain"]:

{
  "domains": ["apify.com", "stripe.com", "basecamp.com"],
  "invalid": ["not a domain"],
  "duplicates_removed": 1
}

Pricing

$0.003 per domain enriched (= $3 per 1,000 domains) on Apify, pay per event, plus Apify's $0.00005 Actor-start event. Only domains that return a result row are charged; unreachable, robots-blocked and invalid domains are free.

How it compares with alternatives

OptionGood forTrade-offs
Doing it by handA handful of companiesSlow; easy to miss imprint pages and obfuscated emails
Writing your own scraperFull controlrobots.txt handling, page discovery, email de-obfuscation, phone parsing and email validation to build and maintain
B2B contact databases (for example Hunter, Apollo, ZoomInfo)Finding named people, job titles and personal work emails from large pre-built databasesSubscription pricing; data comes from their database rather than a live read of the company's site
Fairquery Contact EnricherLive, per-domain company contact data with source URLs and validated emails, pay per domainOnly what the company publishes on its own site; role inboxes by default, no person search; JavaScript-only sites yield less

FAQ

How can I get a company's contact email from its website domain?

Crawl the homepage and its contact, about and imprint pages, extract mailto links, JSON-LD and obfuscated emails, and validate the domain's MX records. The Fairquery Website Contact & Company Enricher does this per domain for $0.003 and returns validated role emails with the page they were found on.

Does it find personal email addresses of employees?

No. By default it returns only role/generic inboxes such as info@, sales@ or hello@ (emailScope 'role'). 'business' adds named addresses published on the company's own domain. It never returns personal LinkedIn profiles and does not search for people.

Does it respect robots.txt?

Yes. It reads robots.txt (RFC 9309), honours Disallow and Crawl-delay for user agent FairqueryBot, makes one request at a time per site with a 1 second default delay, and reports pages_blocked_by_robots.

How fast is it?

About 3-8 seconds per domain with the default settings and 5 domains in parallel, so 100 domains take roughly 1-3 minutes. Our single-domain test run took 5.1 seconds.

What does it cost?

$0.003 per domain enriched on Apify. Unreachable, robots-blocked and invalid domains are free.

Why are some fields empty?

It only returns what the company publishes on the crawled pages. Sites that render contacts with JavaScript only, or block datacenter IPs, return fewer fields, because it uses plain HTTP without a browser or proxy.

Use responsibly: business contact data can still be personal data under GDPR/UK GDPR. Have a lawful basis, honour opt-outs, and follow anti-spam law (CAN-SPAM, ePrivacy/PECR) when you contact anyone. DNS checks cannot prove a mailbox exists.

Source and docs: github.com/fairquery/website-contact-company-enricher (MIT) · Apify Store · all Fairquery tools