Contact Page Finder: Find Contact Page & Contact Form URLs
Pricing
from $0.64 / 1,000 sites
Contact Page Finder: Find Contact Page & Contact Form URLs
Contact page finder API: find contact page URLs and contact form pages for any website from a list of domains. Checks homepage links, common paths and the sitemap, detects the contact form, and returns public emails, phones and social links. One row per site.
Pricing
from $0.64 / 1,000 sites
Rating
0.0
(0)
Developer
Data Done Right
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
This contact page finder takes a list of domains or website URLs and returns, for each site, the contact page URL, the page that holds the contact form, and the contact details the site publishes (emails, phone numbers, LinkedIn, X, Facebook and Instagram links). It looks at the homepage links first, then common paths like /contact and /kontakt, then the sitemap, and it only reports a page after it opened it and checked that it really is a contact page. Use it to enrich lead lists, prepare outreach research, check that your own sites have a working contact page, or let an AI agent find where to write to a company.
You always get one row per website you give, even when nothing was found, so lists stay aligned. You pay only for sites where a contact page or contact form was found.
Find contact page URLs for a list of websites
- Paste domains or URLs into Websites (
apify.com,https://www.mozilla.org/en-US/, ...). Any URL is reduced to the site root. - Run it. Each site is read politely: robots.txt first, usually 2 to 4 pages, 10 at most.
- Download one row per site as JSON, CSV or Excel, or read it through the Apify API.
What the contact page finder does
- Three ways to find the page, cheapest first. (1) Links on the homepage whose text or address says contact, kontakt, contacto, contato, contatti, nous contacter, get in touch and similar. (2) Common paths:
/contact,/contact-us,/about/contact,/get-in-touch,/supportand locale variants such as/kontakt,/contacto,/contato,/contatti, tried first when the homepage language matches. (3) The sitemap, from robots.txt or/sitemap.xml. The next step only runs when the earlier ones found nothing. - Nothing counts until it was checked. A page must answer HTTP 200, must not redirect to the homepage, must not be a login wall or a "404" page served with status 200, and a guessed page must also show a contact signal (a contact title, a form, or published mailto / tel links). A site that answers 200 for every URL is therefore reported as
not_found, not as a made-up hit. - Contact form finder. It checks whether the contact page has a form with email or message fields: a plain HTML form, or an embedded Typeform, HubSpot, Jotform, Google Forms, Tally and similar widget. Newsletter, search and login forms are ignored. If the contact page has no form, up to two other candidate pages (for example
/contact-sales) are checked and the one with the form becomesformUrl. - Public contact details, as published.
mailto:andtel:links plus visible emails and phone numbers on the homepage and contact page. Each email is markedrole(info@, support@),personal(jane.doe@) orunknown. Obfuscations likename [at] site [dot] comand Cloudflare-protected addresses are decoded. Nothing is guessed or verified. - Social profiles. LinkedIn, X, Facebook and Instagram profile links the site links to. Share buttons and tweet intents are ignored.
- Redirects work.
python.orgtowww.python.org,notion.sotonotion.com: the homepage may move to another domain once, and that domain's robots.txt is read as well. - Safe and polite. robots.txt is obeyed (wildcards,
$, Crawl-delay up to 10 s), requests are spaced out, an honest user agent is used (ContactPageFinderBot), no login is attempted, no CAPTCHA or bot check is bypassed, and localhost, private networks, link-local and cloud-metadata addresses are refused, also through DNS tricks and redirects.
Input example
{"websites": ["apify.com", "https://www.mozilla.org/en-US/", "eff.org"],"maxSites": 100,"followHomepageLinks": true,"checkCommonPaths": true,"checkSitemap": true,"detectForm": true,"extractPublicContacts": true,"maxRequestsPerSite": 10,"concurrency": 5,"delaySecs": 1}
Only websites is required. Turn off checkCommonPaths or checkSitemap for fewer requests, detectForm to skip the form check, or extractPublicContacts if you only want URLs. includePersonalEmails: false keeps only role mailboxes and unclassified aliases.
Output example
{"inputIndex": 0, "input": "apify.com", "domain": "apify.com", "homepageUrl": "https://apify.com/","status": "found","contactPageUrl": "https://apify.com/contact","alternates": ["https://apify.com/contact-sales/demo"],"hasContactForm": true, "formUrl": "https://apify.com/contact-sales", "formType": "html","emails": [{"email": "hello@apify.com", "type": "role", "source": "mailto", "page": "https://apify.com/contact"}],"phones": [],"socialLinks": {"linkedin": "https://www.linkedin.com/company/apify", "x": "https://x.com/apify", "facebook": null, "instagram": null},"confidence": "high", "score": 85, "evidence": "homepage link", "checkedUrls": 3,"note": null, "charged": true}
status:found(a contact page or form page was found and checked),not_found(the site was read, no contact page we can find),blocked(robots.txt or a bot check stopped us),unreachable(DNS, connection, timeout, server error) orinvalid(not a public website, such as an IP address or an internal name). Onlyfoundis charged.contactPageUrlis the best candidate.alternateslists other candidate URLs from links or the sitemap (not all of them were opened).formUrlis the page that hosts the form (not the form's action URL).evidencesays how it was found:homepage link,common path,sitemaporhomepage form(a single-page site whose form is on the homepage).confidence(high,medium,low) andscore(0 to 99) come from the evidence plus the page check: a contact title, a form, published contact details.checkedUrlsis the number of pages read for this site (robots.txt not counted).noteexplains why a site has no result.- A SUMMARY record in the key-value store counts rows by status and the charged sites.
Contact form finder: does the page have a form?
hasContactForm is true when the contact page, or another candidate page, has a form with an email or message field. formType is html for a normal form and embedded:Typeform, embedded:HubSpot and so on for widgets. When you turn detectForm off, hasContactForm is null. A form that is drawn only by JavaScript without a recognisable embed is not seen.
Contact Page Finder API
Call it from the Apify API, Python, JavaScript, Make, Zapier or n8n. Example with the Apify Python client:
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("data-done-right/contact-page-finder").call(run_input={"websites": ["apify.com", "mozilla.org"], "detectForm": True})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["domain"], row["status"], row["contactPageUrl"], row["formUrl"])
Use it in Claude, ChatGPT and Cursor
Connect Apify's MCP server (mcp.apify.com) and your AI assistant can call this contact page finder itself. For example: "find the contact page and contact form for these 20 companies and tell me which ones have a form." The main input is websites; the rows come back with the URLs, the form flag and the public emails and phone numbers.
How much does it cost
Pay per event, with no per-run start fee: $0.0008 per site where a contact page or contact form was found (event site). not_found, blocked, unreachable and invalid sites are free, and so are duplicate domains in your list (they get a row, but are crawled and charged once). 1,000 sites that each have a contact page cost about $0.80. Paid Apify plans get 10% (Silver) to 20% (Gold and up) off. Other contact page tools on Apify charge about $0.001 to $0.005 per site. maxSites caps the bill, and if you set a maximum spend per run the Actor stops cleanly when it is reached and keeps the rows already delivered (rows after the limit are not delivered).
Responsible use
- A published address is not permission to email it. In the EU and UK, B2B outreach needs a documented legitimate interest (GDPR Art. 6(1)(f)) and a way to object; some countries require prior consent. In the US, CAN-SPAM requires honest headers, a physical address and a working opt-out. CASL (Canada) and other laws are stricter.
- Do not harvest personal addresses for bulk mail. This tool is built to find where to reach a company: the contact page, the contact form and the role mailboxes the company chose to publish. Addresses that look like a person are marked
personal, and you can leave them out withincludePersonalEmails: false. Use the contact form or the role mailbox for first contact, keep a suppression list, and honour opt-outs. - Only public pages are read, robots.txt is obeyed, no login is used, and the crawl is slow and small on purpose.
Honest limits
- JavaScript-rendered sites. Pages are read as static HTML. A site that draws its navigation or contact form with JavaScript may show no link and no form. You then get
not_foundor a contact page withhasContactForm: false. A browser-based crawl is not part of this Actor. - Bot protection. Sites behind Cloudflare, Akamai, AWS WAF or similar may answer 403, 429 or a challenge page. Those rows are
blockedand free. No CAPTCHA or bot check is bypassed. A proxy can help for sites that block data-center IPs only. - Contact pages without the word "contact". A page called
/reach-outor/say-hiwith a non-matching link text will be missed. Support and help links are listed asalternates; such a page becomes the result only when it has a contact form. - One contact page per site. For large companies with many regions or products you get the best single candidate plus alternates, not every office.
- Not verified. Emails and phone numbers are shown as published. Nothing is sent, called or validated.
- A few pages per site. The default budget is 10 pages. Very large sites with the contact page deep in a menu or only in a sitemap index of many files may not be covered.
- Social links come from the homepage and contact page only. A site that links to a share button instead of its profile has no profile link.
FAQ
How do I find the contact page of a website?
Add the domain to Websites. The Actor reads the homepage, follows the contact link if there is one, tries common paths like /contact and /kontakt, and checks the sitemap, then returns the checked URL in contactPageUrl.
How do I find a contact form URL?
Look at formUrl and hasContactForm. formUrl is the page that hosts the form. If the contact page itself has none, the Actor looks at up to two other candidate pages such as /contact-sales.
Does it work for non-English sites?
Yes for the usual contact words in German, Spanish, Portuguese, Italian, French, Dutch, Scandinavian languages, Polish, Czech, Turkish, Finnish, Hungarian, Russian and common Japanese, Chinese and Korean link texts. Locale paths are tried first when the page language matches.
Why is my site blocked?
Either its robots.txt disallows the page for this bot, or the server answered 401, 403 or 429, or showed a bot-check page. The Actor does not try to get around any of those, and blocked sites are free.
Why not_found when the site obviously has a contact page?
Most often the link is drawn by JavaScript, the page has a name without a contact word, or the site is a single page with an email in the footer. Add the exact URL to your own list, or look at alternates and note.
Are duplicate domains charged twice?
No. Each input gets its own row, but a domain is crawled once and charged once.
Does it send emails or fill in contact forms?
No. It only reads public pages. It never submits a form.
Related tools
- Work Email Finder: Find Email by Name & Domain (No SMTP): once you know the company, find the likely work email of a person there.
- Google Sheets Import & Export: Apify Data, No Login: send the rows to a Google Sheet.
- Slack Notifications: Send Data to Slack, Discord & Email: get an alert when a run is done.