Company Website Contact Info Scraper avatar

Company Website Contact Info Scraper

Pricing

from $1.00 / 1,000 successfully parsed html pages

Go to Apify Store
Company Website Contact Info Scraper

Company Website Contact Info Scraper

Extract emails, phone numbers and social links from company websites or domain lists. Respects robots.txt, CRM-ready output, MX check, $1 per 1,000 pages, failed pages free.

Pricing

from $1.00 / 1,000 successfully parsed html pages

Rating

0.0

(0)

Developer

Ye Qiangwei

Ye Qiangwei

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Company Website Contact Scraper — Emails, Phone Numbers & CRM Export

Turn a list of company websites into source-linked public email addresses, phone numbers and social profile links. Each company is summarized in one dataset row, ready for review or CRM enrichment. Choose perContact for a flat contact export.

What you get

  • Public email addresses, phone numbers and social profile links found on the company pages you supply.
  • Contact, About, Legal, Team and Support page discovery within each company’s registered domain.
  • Source URLs for each contact, plus page results and company status for review.
  • Company rows with ready-to-export CRM fields, or one row per contact with perContact.
  • Configurable page and spending limits, with fees based on successfully parsed HTML pages.

Who is it for?

Sales operations teams enriching company lists, agencies reviewing client contact details, and researchers organizing public business directories. Export primaryEmail, primaryPhone, contactPageUrl, emailsFlat and phonesFlat directly to CSV for CRM review.

The Actor reads static HTML. It does not render JavaScript or verify that an email address exists. Coverage depends on what each website publishes and allows the Actor to access.

Pricing

EventPrice (USD)When charged
run-start$0.00005 per run (nominal startup fee)Once for a validated new run, including runs with failed websites or no contacts
page-fetched$0.001 per page ($1.00 / 1,000 pages)Once for each successfully fetched and parsed HTML page, including pages without contacts

There is no per-contact or dataset-row event fee. Finding ten contacts on one page still costs one page event. The homepage counts toward both the page budget and the price.

Robots requests, redirect hops, duplicate final pages, HTTP failures, non-HTML responses, login pages, protection challenges, timeouts and parsing failures do not incur page events.

For 100 companies × about 8 successful pages each = 800 pages, one run costs $0.00005 + 800 × $0.001 = $0.80005 (about $0.80). Actual successful page counts determine the price.

Other single-run examplesActor event fees
8 successful pages$0.00805
1,000 successful pages$1.00005
All websites fail, with enough budget to start$0.00005

These examples cover Actor event fees. See the Store pricing panel for the effective price and any other platform charges.

Spending limits and billing status

Set the run’s maximum total charge to control spending. The Actor uses the lower of that limit and ACTOR_MAX_TOTAL_CHARGE_USD, after subtracting charges already known to the SDK, including any automatic platform startup event. It reserves capacity before fetching each page and stops scheduling pages when the remaining budget cannot cover the next event.

Before any automatic platform charges, the minimum Actor event budget is $0.00005 to start, or $0.00105 for startup plus one successful page. A budget between those amounts permits only the startup event, with no page requests. Zero budget permits no events; fractions smaller than one microdollar are rounded down.

All companies remain in the output when billing stops:

  • Companies with pending pages, or not yet started, receive CHARGE_LIMIT for budget exhaustion or BILLING_STOPPED for a billing/storage failure. Their status is partial if a page was fetched, otherwise skipped.
  • limits.chargeLimitReached is true only when budget exhaustion affects that company. Completed companies keep their original status and flags. Independently blocked companies keep blocked.
  • The key-value store record SUMMARY contains the global stop reason. Check page-level billing for uncertain charges: a company can retain its extraction status if its last page’s charge is uncertain and no pages remain.

An uncertain charge or receipt-storage failure stops further charging; uncertain events are never retried. Receipts are saved in batches to CHARGE-CHECKPOINT. Forced termination can leave the latest receipts or company output unsaved, so checkpoints do not replace platform billing records. Automatic migration/restart using existing run storage is refused to prevent duplicate charging.

Input

Provide exactly one of startUrls or domains, containing 1–1,000 entries. URLs may include a path: https://example.org/contact starts at that exact page; the homepage is not automatically added. URLs sharing a registered domain are combined into one company and share one page budget. The public suffix list, including private suffixes, keeps independent tenants such as a.github.io and b.github.io separate.

{
"startUrls": [
{ "url": "https://example.com/" },
{ "url": "https://example.org/contact" }
],
"maxPagesPerDomain": 8,
"maxConcurrency": 5,
"includeSubdomains": true,
"requestIntervalMs": 1000,
"globalIntervalMs": 100,
"timeoutMs": 15000,
"outputMode": "perCompany",
"checkMx": false,
"defaultCountry": "GB"
}

Alternatively:

{
"domains": ["example.com", "example.org"],
"outputMode": "perContact"
}

Bare domains use HTTPS, with no automatic HTTP or www fallback. JSON/API input also accepts URL strings in startUrls; the Store URL editor uses { "url": "..." } objects.

Only the URL is used. Standard request-list fields such as uniqueKey, userData and headers are accepted but ignored; method, if supplied, must be GET. Request-list files, credentials, login paths, cookies and proxy options are unsupported.

OptionDefaultLimits / behavior
maxPagesPerDomain81–30 page candidates examined, including failed or robots-disallowed candidates; includes supplied seed pages
maxConcurrency51–20 concurrent company workers; one HTTP request at a time per registered domain
includeSubdomainstrueFollow relevant links and redirects within the registered domain. If false, allow only hostnames explicitly provided in the input, including for robots redirects; company grouping stays by registered domain
requestIntervalMs1,000100–60,000 ms between request starts for a company; robots Crawl-delay takes precedence
globalIntervalMs10020–10,000 ms between global request starts, including robots and redirect hops
timeoutMs15,0001,000–60,000 ms per DNS lookup and per HTTP hop, including body transfer; separate from scheduling delays
outputModeperCompanyperCompany or perContact
checkMxfalseDNS MX lookup only, cached per email domain, with a 3-second lookup timeout
defaultCountryunsetOptional uppercase country code such as GB or US for national phone numbers; no country is guessed

After the supplied pages, the Actor follows only linked pages with relevant anchor text or paths. It does not guess contact paths or open arbitrary news/product pages. It queues at most 3,000 relevant links per company and examines no more than the configured page budget.

Matching covers common English phrases such as “get in touch”, “reach us” and “enquiries”, plus selected French, Spanish, Italian, Portuguese, Dutch, German, Chinese and Japanese terms. This is a limited keyword list, not full language coverage or translation. Uncommon labels may be missed; broad words such as “connect” and “feedback” alone do not qualify.

Output example

One illustrative company row for a fictional business (not collected from a live website):

{"domain":"northstar-studio.co.uk","companyName":"Northstar Studio Ltd","primaryEmail":"hello@northstar-studio.co.uk","primaryPhone":"+442079460958","contactPageUrl":"https://northstar-studio.co.uk/contact","emailsFlat":"hello@northstar-studio.co.uk;sales@northstar-studio.co.uk","phonesFlat":"+442079460958","pagesFetched":8,"pagesFailed":0,"status":"succeeded"}

The compact example selects CRM columns. Full company rows also contain nested contacts, page evidence and billing details as shown below.

CSV columnMeaning
domain, companyNameRegistered company domain and published organization name; name may be empty
primaryEmailFirst general business/role email by source priority, falling back to a suspected personal address; empty if none
primaryPhoneFirst observed phone by source priority; may be a national number when no country was provided
contactPageUrlBest fetched contact-path page, falling back to a prioritized page with observed contacts; empty if none
emailsFlat, phonesFlatDeduplicated values joined with semicolons, ordered with the primary value first; empty strings if none
status, pagesFetched, pagesFailedCompany outcome and examined-page results; check limitations before treating missing data as absent

Export the default perCompany Dataset as CSV to use these columns. primaryEmail, primaryPhone and contactPageUrl are JSON null when unavailable. Phone extensions stay in the phone value.

Source priority is Contact > Impressum/Legal/Privacy > About/Company > Team > Support > homepage > other paths, with the contact value breaking ties. Role emails always precede suspected personal addresses. This ranking does not establish who is best to contact. Flat fields include suspected personal addresses too; review them before import.

Full illustrative row:

{
"domain": "acme-company.com",
"companyName": "Acme Company",
"primaryEmail": "info@acme-company.com",
"primaryPhone": "+442079460958",
"contactPageUrl": "https://acme-company.com/contact",
"emailsFlat": "info@acme-company.com",
"phonesFlat": "+442079460958",
"emails": {
"general": [
{
"value": "info@acme-company.com",
"sourcePages": ["https://acme-company.com/contact"]
}
],
"personal": []
},
"phones": [
{
"value": "+442079460958",
"e164": "+442079460958",
"extension": null,
"raw": "+44 20 7946 0958",
"sourcePages": ["https://acme-company.com/contact"]
}
],
"socialLinks": [
{
"value": "https://www.linkedin.com/company/acme-company",
"sourcePages": ["https://acme-company.com/contact"]
}
],
"sourcePages": [
{
"requestedUrl": "https://acme-company.com/contact",
"url": "https://acme-company.com/contact",
"status": "fetched",
"billing": "confirmed",
"httpStatus": 200,
"redirectCount": 0,
"contacts": [
{ "type": "email", "value": "info@acme-company.com" },
{ "type": "phone", "value": "+442079460958" },
{ "type": "social", "value": "https://www.linkedin.com/company/acme-company" }
]
}
],
"pagesFetched": 1,
"pagesFailed": 0,
"status": "succeeded",
"failureReasons": [],
"scrapedAt": "2026-10-23T00:00:00.000Z",
"billing": { "mode": "platform", "pagesConfirmed": 1, "pagesUnknown": 0 },
"limits": { "maxPagesPerDomain": 8, "pageLimitReached": false, "chargeLimitReached": false },
"mxDisclaimer": null
}

Each contact has its own sourcePages URL list. The company’s top-level sourcePages holds page outcomes, contact references and billing confirmations. Fetched pages also include parsedAt, chargeReceiptId and chargeCheckpointKey to link them to billing receipts.

companyName comes from explicit organization JSON-LD or og:site_name when available; it may be null.

General role addresses such as info@, sales@, support@ and contact@ are separated from suspected personal addresses. This is a local-part heuristic, not identity verification. The Actor only extracts addresses actually published on the supplied company's pages; it never guesses employee addresses. Contacts are deduplicated within a company and retain all observed source pages. The same contact can appear for different companies.

Phone numbers are validated and normalized using numbering-plan metadata. National numbers require defaultCountry; otherwise plausible numbers found in explicit tel: links are retained with e164: null. Extensions are preserved. A valid format does not establish ownership or whether a phone is active.

Common [at], (at), [dot] and Cloudflare email-protection XOR encodings are decoded locally. Scripts, styles, image filenames, placeholder/test domains, no-reply addresses and common telemetry addresses are filtered. This does not solve CAPTCHAs or bypass access controls.

With checkMx: true, each email includes mx.status (present, no_mx, null_mx or unknown), exchanges and deliverability: "not_verified". MX presence does not mean an address exists or is deliverable. No SMTP connection, message sending or mailbox probing occurs. A missing MX may still permit SMTP fallback; this is an observation, not a deliverability verdict.

perContact produces rows such as:

{
"domain": "acme-company.com",
"companyName": "Acme Company",
"contactType": "email",
"category": "general",
"value": "info@acme-company.com",
"sourcePages": ["https://acme-company.com/contact"],
"status": "succeeded",
"pagesFetched": 1,
"pagesFailed": 0
}

Flat rows also include the five CRM fields, company metadata, failureReasons, billing, limits and scrapedAt.

  • sourcePages always contains that contact’s source URL list.
  • pageResults contains the company’s page outcomes (the top-level sourcePages in perCompany output).
  • Company counters repeat on each contact row: do not sum them across contacts.
  • Companies with no contacts retain a row with contactType: null, value: null, sourcePages: [] and the company’s page evidence in pageResults. If no pages were attempted, pageResults is also empty.

Understanding results

StatusMeaning
succeededContacts were found within the examined pages, without a reported incomplete condition
emptyExamined pages produced no contacts, without a reported incomplete condition
partialFailed/skipped candidates, the page budget or a charge stop left the company incomplete
failedNo page was successfully fetched and a page failure was reported
blockedAccess was refused; may retain contacts collected before the refusal
skippedThe company was not fetched, for example because the spending limit was reached before it started

No status guarantees that every website contact was found. pagesFetched counts parsed HTML pages, including empty pages. pagesFailed counts failed examined candidates, including robots exclusions. Robots requests and redirect hops are excluded from both counters. Check page-level billing for uncertain charge outcomes.

Access rules and limitations

Website access

The Actor reads each origin’s robots.txt as CompanyContactsBot. Disallowed paths and unavailable or ambiguous rules are skipped conservatively. A 404/410 allows normal evaluation. Transient network failures and HTTP 5xx receive at most one robots retry per origin per run, through the same rate limits; deterministic refusals are cached without retry. Crawl-delay above 60 seconds results in a skip.

HTTP 401/403/429, detected login walls and protection challenges stop that company without retries or IP changes. Other page failures are reported without retrying. The Actor sends no target cookies or credentials, uses no proxies, submits no forms, and does not execute JavaScript, load images or follow social profiles.

Pages and robots fetches allow up to five redirect hops, within the original registered domain. Every destination is checked for private/reserved addresses, mixed public/private DNS answers are rejected, and connections are pinned to the validated address. Off-domain redirects are reported as incomplete.

Coverage and resource limits

  • Contacts must appear in returned HTML. JS-only data, images of contact details, advanced obfuscation and details requiring interaction may be missed.
  • Social links come from a known host list; unrecognized hosts may be omitted. Language matching, filtering, phone parsing, company names and challenge detection are heuristic and may miss data or produce false positives.
  • Compressed and decoded HTML are each limited to 5 MiB; robots.txt is limited to 512 KiB. gzip, deflate and Brotli are supported. Unsupported/binary/invalid character encodings fail without page fees; ordinary imperfect HTML is accepted.
  • Default memory is 1,024 MiB (minimum 512 MiB). Large pages and higher concurrency increase memory use; these settings do not guarantee against out-of-memory failures.
  • Cross-run change and deletion tracking are not supported.

Responsible use

Supply only public company pages you are authorized to collect. Review suspected personal addresses before use and apply appropriate retention and deletion rules. Public availability and robots.txt access do not establish permission to republish information or contact people; comply with website terms and applicable privacy and marketing rules.

FAQ

Does it support JavaScript websites? No JavaScript is executed. Static HTML returned by a JavaScript-based site can be parsed, but contacts rendered only by scripts or interaction are unsupported.

Does it respect robots.txt? Yes. Each origin is checked with CompanyContactsBot; disallowed paths and unavailable or ambiguous robots responses are skipped conservatively. HTTP 401/403/429 and detected access challenges stop the company without retries.

Are emails verified using SMTP? No. The optional MX check uses DNS only, never connects to SMTP, sends messages or probes a mailbox. MX presence does not verify an address or deliverability.

Who is responsible for personal data and outreach compliance? You are responsible for your lawful basis, permissions, privacy notices, retention and deletion, and compliance with applicable rules such as GDPR and CAN-SPAM. Public contact details can still be personal data. Review the source and intended use before exporting, storing or contacting anyone; this Actor does not establish legal permission.