Website Contact Form Scraper avatar

Website Contact Form Scraper

Pricing

from $9.60 / 1,000 item extracteds

Go to Apify Store
Website Contact Form Scraper

Website Contact Form Scraper

Crawl public websites and bounded contact/about pages. Extract published emails, phone numbers, social profiles, contact URLs, form fields, and page provenance, rendering JavaScript when needed.

Pricing

from $9.60 / 1,000 item extracteds

Rating

0.0

(0)

Developer

Stas Persiianenko

Stas Persiianenko

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 days ago

Last modified

Share

Turn a list of public websites into source-attributed contact records. Website Contact Form Scraper finds published emails, website contact numbers, social profiles, contact/about URLs, and contact-form structure while preserving the page where each value was found.

It requests lightweight HTML first and renders JavaScript only when needed. You can also force browser rendering for a client-side contact page or force HTTP-only crawling for predictable low-cost jobs.

What does Website Contact Form Scraper do?

For each supplied website, the Actor:

  1. validates that the target is a public HTTP(S) address;
  2. loads the homepage or supplied page;
  3. discovers bounded same-site contact, support, about, team, help, and legal pages;
  4. renders client-side pages with Chromium when automatic detection requires it;
  5. extracts public email addresses, phone numbers, and social links;
  6. describes contact forms without submitting them;
  7. returns one normalized website record with page-level provenance.

The Actor never submits a form, sends a message, logs in, or guesses private contact data.

Who is it for

  • Lead enrichment teams adding public contact channels to prospect domains.
  • Sales operations teams preparing website records for a CRM import.
  • Directory operators checking contact and social links published by listed organizations.
  • Researchers comparing how organizations expose contact pages and forms.
  • Developers building repeatable website contact extraction into data pipelines.

If you need only one row per displayed email, use Website Email Extractor. If you need static business contact details including postal-address text, use Website Contact Details Scraper.

Why use this website contact extractor?

  • JavaScript-aware: automatic HTTP-first crawling falls back to Chromium for page shells or pages without usable contact/link signals.
  • Bounded crawling: page and depth controls prevent an input website from becoming an unbounded crawl.
  • One record per website: convenient for spreadsheet, CRM, and database enrichment.
  • Contact-form structure: captures action, method, field names/types, labels, and required flags without submitting data.
  • Page provenance: every page records its URL, title, rendering method, and extracted values.
  • Public-target validation: local/private network destinations and unsafe redirects are rejected.
  • No automatic paid proxy fallback: proxy costs remain under your control.

What data can I extract?

FieldDescription
websiteUrlNormalized input URL
finalUrlHomepage URL after redirects
domainFinal hostname
websiteNameName inferred from metadata or title
emailsUnique published emails across crawled pages
phoneNumbersUnique published phone strings
socialProfilesNetwork, profile URL, and source page
contactPageUrlsSame-site contact, support, or help URLs
aboutPageUrlsSame-site about, company, or team URLs
contactFormsForm action, method, name, and public field metadata
pagesPage URL, title, rendered flag, and per-page contacts
pagesCrawledNumber of successfully inspected pages
pagesFailedURL and concise failure reason for failed pages
foundContactDetailsWhether useful public contact evidence was found
scrapedAtISO 8601 completion timestamp

Empty arrays mean that the inspected pages did not expose that field. They do not prove that the organization has no contact channel elsewhere.

How to scrape a website contact form

  1. Open the Actor in Apify Console.
  2. Add one or more public website URLs.
  3. Keep JavaScript rendering set to Automatic for most jobs.
  4. Choose a page limit and link depth.
  5. Click Start.
  6. Open the Dataset tab to review one result per input website.
  7. Export results as JSON, CSV, Excel, XML, or RSS, or consume the dataset API.

A useful first run is:

{
"startUrls": [{ "url": "https://apify.com" }],
"maxWebsites": 1,
"maxPagesPerWebsite": 3,
"maxDepth": 1,
"renderingMode": "auto"
}

Input parameters

startUrls

Required list of public HTTP(S) websites. Domain-only values such as apify.com are normalized to HTTPS. Duplicate strings are processed once.

maxWebsites

Maximum unique input websites to process. The default is 10 and the maximum is 1,000.

maxPagesPerWebsite

Maximum successful pages inspected for each website. The default and maximum are 5, keeping browser-mode cost and runtime bounded. A smaller value lowers runtime; a larger value can improve coverage on sites with several contact or team pages.

maxDepth

Maximum same-site contact/about link depth from the supplied page. Use 0 for only the supplied URL, 1 for its relevant links, or up to 3 for deeper bounded discovery.

renderingMode

  • auto — request HTML first; render when the response fails, looks like a JavaScript shell, or exposes no usable contact/link signals.
  • browser — render every inspected page with Chromium.
  • http — never launch Chromium.

includeSubdomains

When enabled, relevant pages on subdomains are eligible for crawling. It does not turn the run into a general subdomain crawler.

proxyConfiguration

Optional Apify Proxy or custom proxy settings. The Actor does not silently switch to residential proxies. Choose and pay for a proxy only when your target requires one and you are authorized to access it.

Output example

A shortened real-behavior example looks like this:

{
"websiteUrl": "https://apify.com/",
"finalUrl": "https://apify.com/",
"domain": "apify.com",
"websiteName": "Apify",
"emails": ["hello@apify.com"],
"phoneNumbers": [],
"socialProfiles": [
{
"network": "github",
"url": "https://github.com/apify",
"sourceUrl": "https://apify.com/contact"
}
],
"contactPageUrls": ["https://apify.com/contact"],
"aboutPageUrls": ["https://apify.com/about"],
"contactForms": [],
"pages": [
{
"url": "https://apify.com/contact",
"title": "Contact us · Apify",
"rendered": false,
"emails": ["hello@apify.com"],
"phoneNumbers": [],
"socialLinks": [],
"contactFormCount": 0
}
],
"pagesCrawled": 3,
"pagesFailed": [],
"foundContactDetails": true,
"scrapedAt": "2026-08-24T12:00:00.000Z"
}

The complete record includes all social links and all inspected page provenance.

How much does it cost to enrich websites with public contacts?

Pricing uses one start event per run plus one item event per website returned. Contact fields, social profiles, contact forms, and page provenance included in that website record have no separate charge.

Current BRONZE pricing:

  • run start: $0.005;
  • website processed: $0.016.

Examples at BRONZE, excluding optional proxy charges:

WebsitesEstimated Actor price
1$0.021
10$0.165
100$1.605

Subscription tiers apply lower per-website rates. Actual platform compute and any user-selected proxy usage appear separately in Apify usage details.

JavaScript rendering strategy

Automatic mode is designed to avoid paying browser cost on ordinary server-rendered pages. It uses browser rendering when:

  • the HTTP request fails and a browser may still load the page;
  • visible HTML resembles a client-side shell;
  • the HTML provides neither direct contact evidence nor bounded contact/about links.

Browser mode blocks images, media, and fonts because they are not needed for contact extraction. Scripts, styles, and data requests remain available so client-side pages can render.

Contact form data and website contact form examples

A discovered form is included only when its fields or text look contact-related. The Actor records public HTML metadata such as:

  • form page and action URL;
  • GET or POST method;
  • form name or ID;
  • input, textarea, and select names;
  • control types, labels/placeholders, and required flags.

It does not type into fields, bypass validation, solve CAPTCHAs, or submit the form. Use the metadata to compare forms or route a later authorized workflow.

Prospect enrichment workflow

For recurring enrichment:

  1. export website URLs from your CRM;
  2. map them to startUrls;
  3. schedule the Actor daily, weekly, or monthly;
  4. join dataset rows back to your domain key;
  5. store scrapedAt and page provenance with the contact values;
  6. review changed values before outreach.

The Actor returns current observations. Change detection and CRM updates belong in your downstream workflow.

Export and integrations

The default dataset works with:

  • Apify CSV, JSON, Excel, XML, and RSS exports;
  • webhooks triggered after successful runs;
  • Make and Zapier Apify integrations;
  • Google Sheets or database loaders;
  • Python, JavaScript, and REST API clients;
  • scheduled Apify Tasks.

One item represents one input website, which makes domain-keyed joins straightforward.

Run with the Apify API using cURL

curl -X POST \
"https://api.apify.com/v2/acts/automation-lab~javascript-website-contact-extractor/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startUrls": [{"url": "https://apify.com"}],
"maxWebsites": 1,
"maxPagesPerWebsite": 3,
"maxDepth": 1,
"renderingMode": "auto"
}'

Never commit an API token to source control.

Run with JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/javascript-website-contact-extractor').call({
startUrls: [{ url: 'https://apify.com' }],
maxWebsites: 1,
maxPagesPerWebsite: 3,
maxDepth: 1,
renderingMode: 'auto',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Run with Python

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation-lab/javascript-website-contact-extractor").call(
run_input={
"startUrls": [{"url": "https://apify.com"}],
"maxWebsites": 1,
"maxPagesPerWebsite": 3,
"maxDepth": 1,
"renderingMode": "auto",
}
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)

Use with MCP and AI agents

Add the Actor to Claude Code:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=automation-lab/javascript-website-contact-extractor"

Claude Desktop, Cursor, and VS Code setup

Use this MCP configuration in Claude Desktop, Cursor, or VS Code clients that support remote HTTP MCP servers:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/javascript-website-contact-extractor"
}
}
}

Example prompts:

  • “Extract public contact details and provenance from these three company websites.”
  • “Force browser rendering on this contact page and list its public form fields.”
  • “Return one CRM-ready website record for each supplied domain.”

Limits and expected failure behavior

  • Some sites block automated access or require authentication.
  • CAPTCHA, login-only, and private pages are not bypassed.
  • A website may publish no email or phone number.
  • Regex-based phone extraction can omit unusual formats or capture a number that needs human review.
  • Client-side widgets inside blocked third-party iframes may not be visible.
  • Automatic mode is heuristic; force browser when you know contacts render client-side.
  • Page limits intentionally trade completeness for bounded cost and runtime.
  • Redirects to private/local networks are rejected.
  • A failed page is listed in pagesFailed; other successfully fetched pages can still produce a website record.

Tips for better results

  • Start with auto, 3–5 pages, and depth 1.
  • Supply the canonical company homepage instead of a search result URL.
  • Force browser only for websites known to render contact content with JavaScript.
  • Increase page limits before increasing depth.
  • Enable subdomains only when the organization hosts contact pages separately.
  • Use a proxy only when direct access is blocked and your use is permitted.
  • Review provenance before using contact data operationally.

Scrape only publicly accessible pages you are authorized to process. Follow applicable website terms, robots guidance, privacy, database, marketing, and anti-spam laws. Public availability does not automatically grant permission for every downstream use.

Do not use the Actor to target private networks, access authenticated content without authorization, build sensitive-person profiles, or send unsolicited messages. The user is responsible for retention, lawful basis, suppression lists, and outreach compliance.

Troubleshooting

Why did a website return empty contact arrays?

Open pages and pagesFailed. The inspected pages may not publish contact details, the relevant page may exceed your limits, or the website may need browser mode. Try renderingMode: "browser" and a slightly higher page limit.

Why was my URL rejected as a private target?

The Actor blocks loopback, local, link-local, and private network destinations, including redirects. Supply a public website URL.

Why is browser mode slower?

Chromium executes page scripts and waits for the rendered DOM. Automatic or HTTP mode is faster when server-rendered HTML already contains the needed data.

Does the Actor submit contact forms?

No. It records public form structure only.

FAQ

Can I process multiple websites?

Yes. Add them to startUrls and set maxWebsites high enough. Each processed website produces one dataset item.

Can I crawl an entire domain?

No. This is intentionally a bounded contact/about crawler, not a general website crawler.

Are email addresses verified?

They are normalized from public page content but not mailbox-verified. Treat them as observed website data.

Are proxy charges included in the per-website event?

The Actor event price is separate from optional user-selected proxy usage shown by Apify. No residential proxy is enabled automatically.

Can I schedule recurring runs?

Yes. Save the input as an Apify Task and attach a schedule. The Actor returns snapshots; compare datasets in your own workflow when you need change tracking.

What happens when one page fails?

The Actor records that page in pagesFailed and continues with other bounded pages. Invalid top-level input still fails the run with a non-zero status.