Website Contact Scraper: Contact Page & Form Finder, Emails avatar

Website Contact Scraper: Contact Page & Form Finder, Emails

Pricing

from $2.00 / 1,000 website with contacts

Go to Apify Store
Website Contact Scraper: Contact Page & Form Finder, Emails

Website Contact Scraper: Contact Page & Form Finder, Emails

Contact page and contact form finder for company websites: the contact page URL, whether it has a contact form and its type (HTML, HubSpot, Typeform, Google Forms...), plus role emails such as info@, phones and social links. One row per website; pay only when an email, phone or social link is found.

Pricing

from $2.00 / 1,000 website with contacts

Rating

0.0

(0)

Developer

Enis Bodlli

Enis Bodlli

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

0

Monthly active users

8 days ago

Last modified

Security

Limited permissions

Share

A contact page finder and contact form finder for lists of company websites. For each site it returns the contact page URL, whether there is a contact form and what kind (written into the page, or embedded from HubSpot, Typeform, Google Forms, Jotform and other form services), and the company's email addresses, phone numbers and social media links. It reads each site's home page and its contact, about, imprint and legal pages, one row per website. To try it, leave the three sample websites in the input and click Start: the run takes a few seconds.

You pay only for websites where a contact was found. A website with no contact, a site that blocks the visit and a domain that does not exist still get a row, so you can see they were checked, and cost nothing.

It returns company contact points, not people: shared mailboxes such as info@, sales@ or kontakt@, the company's phone numbers and its company pages on social networks. Addresses that look like a person's (firstname.lastname@) are left out and counted.

What you can do with a website contact scraper

  • Build a lead list from domains. Feed in the websites of companies you want to reach and get the general email address, the phone number and the contact page of each.
  • Fill gaps in a CRM. Add the missing email, phone or LinkedIn company page to accounts that only have a website.
  • Reach companies through their contact form. contactFormUrl is the page with the form and contactFormType says how it is made: html for a form in the page, or the service it comes from (hubspot, typeform, google-forms and others). Useful when a company publishes no email address, and for sorting a list by how each company takes enquiries.
  • Check a list of domains. The status of each row tells a working site from one that is gone or that refuses automated visits.
  • Call it from code or an AI agent. Start the Actor through the Apify API and read the rows as JSON.

How to extract emails and phone numbers from websites

  1. Paste the websites under Websites, one per line, as domains (example.com) or URLs. Through the API, pass them as an array.
  2. Optionally change Maximum pages per website, or switch phone numbers or social links off.
  3. Click Start. Each website's row is saved as soon as that website is done, so a run you stop keeps what it finished.
  4. Open the Output tab and export the table as JSON, CSV or Excel, or read it through the API.

Pricing

You pay per website with at least one contact found (an email address, a phone number or a social media link):

Apify planPer 1,000 websites with contactsPer website
Free, Bronze$3.00$0.003
Silver$2.50$0.0025
Gold$2.00$0.002

Plus $0.00005 per run start. Platform usage is included, so there is nothing else to pay. The price does not depend on how many pages are read: a website is charged once. The contact page and contact form come with the row at no extra cost, and a website whose only contact point is a form is not charged.

  • 1,000 websites, 640 of them with a contact: 640 charges. That is $1.92 on the Free and Bronze plans, $1.60 on Silver and $1.28 on Gold. The other 360 websites are in the results at no cost.
  • 50 websites, 31 of them with a contact: 31 charges, $0.093 on the Free and Bronze plans.

Repeated domains are removed before the run, so no website is charged twice. A website is charged at the moment its row is saved. A run that is stopped, fails or is restarted continues where it left off: websites that already have a row are skipped, so they are not charged again.

You can set a maximum charge per run. The Actor then starts a website only while that limit has room for it, stops when the limit is reached, and reports how many websites it did not check.

Input

FieldWhat it does
Websites (websites)The websites to read. Required. Domains or URLs, up to 10,000 per run. Repeated domains are removed; the first entry counts. Only pages on the website's own domain (and its subdomains) are read.
Maximum pages per website (maxPagesPerSite)The home page plus the most likely contact pages. Default 8, at most 20.
Include phone numbers (includePhones)Default on. When off, phones is an empty list.
Include social media links (includeSocialLinks)Default on. When off, every entry of socialLinks is null.

Example:

{
"websites": ["jotform.com", "ideo.com", "contactform7.com", "g2.com"],
"maxPagesPerSite": 5,
"includePhones": true,
"includeSocialLinks": true
}

Output

One row per website, with the contacts from all its pages merged. domain identifies the row. Below is the result of the example input, from a run on 2026-10-21: two websites with contacts and a contact form (one written into the page, one embedded from HubSpot), one whose only contact point is its form, and one that refuses automated visits. Only the first two are charged.

[
{
"website": "jotform.com",
"domain": "jotform.com",
"status": "ok",
"statusReason": "Found 1 email, 1 phone number, 5 social links and a contact form (html) on 5 pages.",
"emails": ["support@jotform.com"],
"personalEmailsSkipped": 0,
"phones": [
{ "text": "+14156343883", "digits": "14156343883" }
],
"socialLinks": {
"linkedin": "https://www.linkedin.com/company/jotform",
"facebook": "https://www.facebook.com/Jotform",
"instagram": "https://www.instagram.com/jotform_official",
"x": "https://x.com/jotform",
"youtube": "https://www.youtube.com/user/TheJotform",
"tiktok": null,
"github": null
},
"contactPageUrl": "https://www.jotform.com/contact/",
"hasContactForm": true,
"contactFormType": "html",
"contactFormUrl": "https://www.jotform.com/contact/",
"pageTitle": "Jotform: Free Online Form Builder | Create Forms in Seconds",
"pagesCrawled": 5,
"checkedAt": "2026-10-21T17:44:09.955Z"
},
{
"website": "ideo.com",
"domain": "ideo.com",
"status": "ok",
"statusReason": "Found 3 phone numbers, 2 social links and a contact form (hubspot) on 3 pages.",
"emails": [],
"personalEmailsSkipped": 0,
"phones": [
{ "text": "+1 (312) 869 6000", "digits": "13128696000" },
{ "text": "+44 (01)207 713 2600", "digits": "44012077132600" },
{ "text": "+1 (415) 615 5000", "digits": "14156155000" }
],
"socialLinks": {
"linkedin": "https://www.linkedin.com/company/ideo",
"facebook": null,
"instagram": "https://www.instagram.com/ideo",
"x": null,
"youtube": null,
"tiktok": null,
"github": null
},
"contactPageUrl": "https://www.ideo.com/contact",
"hasContactForm": true,
"contactFormType": "hubspot",
"contactFormUrl": "https://www.ideo.com/contact",
"pageTitle": "IDEO : Human-centered design",
"pagesCrawled": 3,
"checkedAt": "2026-10-21T17:44:07.643Z"
},
{
"website": "contactform7.com",
"domain": "contactform7.com",
"status": "no_contacts_found",
"statusReason": "No company email, phone number or social link on 4 pages. A contact form (html) was found; a form alone is not charged.",
"emails": [],
"personalEmailsSkipped": 0,
"phones": [],
"socialLinks": { "linkedin": null, "facebook": null, "instagram": null, "x": null, "youtube": null, "tiktok": null, "github": null },
"contactPageUrl": "https://contactform7.com/contact/",
"hasContactForm": true,
"contactFormType": "html",
"contactFormUrl": "https://contactform7.com/contact/",
"pageTitle": "Contact Form 7 | Just another contact form plugin for WordPress. Simple but flexible.",
"pagesCrawled": 4,
"checkedAt": "2026-10-21T17:44:08.201Z"
},
{
"website": "g2.com",
"domain": "g2.com",
"status": "blocked",
"statusReason": "The home page could not be read: HTTP 403 (access denied to automated visits).",
"emails": [],
"personalEmailsSkipped": 0,
"phones": [],
"socialLinks": { "linkedin": null, "facebook": null, "instagram": null, "x": null, "youtube": null, "tiktok": null, "github": null },
"contactPageUrl": null,
"hasContactForm": false,
"contactFormType": null,
"contactFormUrl": null,
"pageTitle": null,
"pagesCrawled": 0,
"checkedAt": "2026-10-21T17:44:07.476Z"
}
]
FieldMeaning
websiteThe website as you entered it.
domainIts host name in lower case, without www.. One row per domain.
statusok, no_contacts_found, blocked or unreachable. See below.
statusReasonOne sentence saying why.
emailsShared and role addresses of the company, lower-cased, without repeats, addresses on the website's own domain first. At most 25.
personalEmailsSkippedHow many addresses were left out because they are not recognisably a shared mailbox.
phonesUp to 10 phone numbers: text as the site shows it, digits with digits only. An international number starts with its country code.
socialLinksThe company's page on LinkedIn, Facebook, Instagram, X, YouTube, TikTok and GitHub, or null.
contactPageUrlThe website's contact page: the page it links to as one or, when it names none, the page with its contact form. null when neither was found.
hasContactFormtrue when a contact form was found on the pages read.
contactFormTypehtml for a form written into the page, or the form service it comes from: hubspot, typeform, google-forms, jotform, microsoft-forms, tally, wufoo, formstack, cognito-forms, zoho-forms, paperform, marketo, pardot or pipedrive. null without a form.
contactFormUrlThe page the form is on, or the form's own address when the contact page links to a form on a service (a Google Form, say). A form on a contact page is preferred, then one on the home page.
pageTitleTitle of the home page.
pagesCrawledHow many pages were read.
checkedAtWhen the website was checked (UTC).

Websites are read in parallel, so rows can be in a different order than your list. Match them on domain. A summary of the run (websites per status, charges, entries that were skipped) is saved as RUN_SUMMARY in the run's key-value store.

What each status means

StatusMeaningCharged
okAt least one email address, phone number or social link was found.Yes
no_contacts_foundThe site was read and shows no company email, phone number or social link on the pages visited. It may still have a contact form (hasContactForm).No
blockedThe site refused the visit: HTTP 401, 403 or 429, a CAPTCHA or JavaScript challenge, or a robots.txt rule.No
unreachableThe domain does not exist, the server did not answer in time, or the home page returned an error.No

Limits

  • Personal-looking addresses are left out. An address is returned only when the part before the @ is a function or a department, in English and the major European languages. A name (jane.smith@), initials, a single first name, or any word the Actor does not know is not returned, only counted in personalEmailsSkipped. The purpose is company contact points, not personal data about individuals. This also drops some harmless addresses with unusual names.
  • Sites that block automated visits are reported, not forced. The Actor sends plain requests from Apify's servers under its own name (website-contact-scraper). It uses no proxies and no browser and solves no CAPTCHAs. A refusal is final, with one exception: when a site answers "too many requests" and names a wait of up to 30 seconds, the Actor waits that long and asks again. A site that refuses comes back as blocked.
  • JavaScript-only sites may show nothing. Pages that build their content in the browser arrive empty. They come back as no_contacts_found, with a note in statusReason.
  • Addresses a site hides on purpose are not decoded, for example Cloudflare email protection or info (at) example.com.
  • Phone numbers are taken from phone links and from numbers next to a label such as "Tel" or "Phone", or written in international form. Fax and mobile numbers, and numbers on team pages, are left out. A number without a label in a national format can be missed.
  • Pages read: the home page and the contact, about, imprint, legal and team pages linked from it, on the same domain. Privacy policies and terms are skipped, because the addresses there mostly belong to others. After 90 seconds no further page of a website is requested, and a page larger than 5 MB is not read.
  • Social links are the profiles a site links to. Personal profiles such as LinkedIn /in/ are skipped; on other networks a company page and a personal one look the same.
  • Contact forms are looked for on the same pages. A form written into the page counts when it asks for a message; search boxes, sign-ins, newsletter sign-ups, page surveys and comment forms do not. A form embedded from a service counts as it is, because the service draws its fields after the page loads. A link to a form on a service counts only on a contact page. A form that a site builds with its own scripts after loading (common on Wix and some page builders), or one on a page the home page does not link to, is not seen. The Actor finds forms; it does not fill them in.

FAQ

The Actor reads public pages of the websites you list, the same pages a visitor sees. It follows each site's robots.txt, does not log in anywhere and does not get around blocks. It returns company contact points and leaves out addresses that look like a person's. What you do with the results is your responsibility: whether and how you may contact a company depends on the laws that apply to you and to them, such as rules on unsolicited email.

Why is there no email for a website?

Many companies publish only a contact form. Look at contactFormUrl and contactPageUrl. If personalEmailsSkipped is above zero, the site lists addresses that were left out. If statusReason mentions JavaScript, the site needs a browser.

Can it find a website's contact form?

Yes. Every row says whether the site has a contact form (hasContactForm), where it is (contactFormUrl) and how it is made (contactFormType): html for a form in the page, which an automation tool can usually fill in, or the service it is embedded from, such as HubSpot, Typeform or Google Forms. It costs nothing extra. Whether you may send a message through a form depends on the laws on unsolicited messages that apply to you and to the company, and on the site's terms.

Why is a website "blocked"?

The site answered a plain, identified request with a refusal. Large consumer sites often do. The Actor reports this and moves on; the row costs nothing.

Can I get the addresses of named people?

No. This Actor returns shared mailboxes only.

How long does a run take?

A website takes a few seconds, and ten are read at a time. In a test on 2026-10-04, 15 company websites from twelve countries took 10 seconds. A site that does not answer takes about a minute before it is reported as unreachable.

Can I check whether the addresses work?

Yes, with Email Validator & List Cleaner, which checks syntax and whether the domain receives mail.

Where do I report a problem?

Open an issue on the Issues tab of this Actor. Name the website and say what you expected to find on it. Issues are answered there.

More Actors from this developer

Contacts and lists:

Jobs:

Company registers: