Website Contact Finder: Emails, Phones & Socials
Pricing
from $3.00 / 1,000 website with contacts
Website Contact Finder: Emails, Phones & Socials
Find emails, phone numbers and social profiles on any list of websites. Reads each homepage plus its contact, about and impressum pages. One flat price per website, never per page; unreachable sites are free.
Pricing
from $3.00 / 1,000 website with contacts
Rating
0.0
(0)
Developer
Southern Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 hours ago
Last modified
Categories
Share
Give it a list of websites. For each one you get one clean row with:
- Emails: from
mailto:links, plain text, Cloudflare "email protection",info [at] shop [dot] com-style spelling, and schema.org data. The address on the site's own domain comes first. - Phone numbers: from
tel:links, schema.org data, labelled text ("Phone:", "Call us on", "Tel.", "Telefon") and clearly phone-shaped local numbers like(02) 4929 1234, converted to international E.164 format (+61249291234) when the country is known. Fax, ABN, VAT and company numbers are left out. - Social profiles: Facebook, Instagram, LinkedIn, X (Twitter), YouTube, TikTok and Pinterest. Share buttons, the website builder's own accounts and staff members' personal profiles on team pages are ignored.
- The contact page URL, whether the site uses a contact form, and a status for every site (read, dead, blocked, parked…).
- Where each item was found (page and method), so you can check any result in a click.
One flat price per website, never per page. We read the homepage plus up to 4 likely pages (contact, impressum, about, team), and sites we can't read cost nothing.
Pricing
| Event | Price | When |
|---|---|---|
website-checked | $0.0005 | The website was reached and read (any number of pages up to your limit) |
contacts-found | $0.003 | At least one email or phone number was found on it |
So 1,000 websites cost at most $3.50, and less when sites have no contacts. A site with only social links is charged $0.0005. Dead, unreachable, blocked, parked and robots.txt-disallowed sites, and invalid input, are free. The log shows the maximum cost before the run starts, and every row has a chargedEvents column.
Why flat? Per-page pricing makes the bill depend on how many pages the crawler decides to open, and users of per-page contact scrapers often report surprise bills. Here you know the cost before you start.
Quick start
- Click Try for free.
- Paste websites, one per line:
acme.com.au,https://www.acme.com/, or evenjane@acme.com(its website is read). Or paste a link to a CSV / TXT file or a Google Sheet (shared as "Anyone with the link can view") in websitesFileUrl. A column namedwebsite,url,domainoremailis used automatically, so exports from Google Maps or OpenStreetMap scrapers work as they are. - Optional: set Default country (e.g.
AU) so local numbers on.comsites become+61…. - Click Start, then open the Output tab: Overview, Emails & phones, Social profiles, Where found (audit), Not readable / skipped or All fields. Download as CSV, Excel or JSON.
Via API:
curl -X POST "https://api.apify.com/v2/acts/southern-data~website-contact-finder/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"websites":["acme.com.au","example.de"],"defaultCountry":"AU"}'
Example row
{"input": "harbourplumbing.com.au","rowStatus": "checked","siteStatus": "ok","primaryEmail": "info@harbourplumbing.com.au","emails": "info@harbourplumbing.com.au; accounts@harbourplumbing.com.au","primaryPhone": "+61249291234","phones": "+61249291234; +61412345678","phonesAsWritten": "(02) 4929 1234; 0412 345 678","facebook": "https://www.facebook.com/HarbourPlumbingNewcastle","instagram": "https://www.instagram.com/harbour.plumbing","contactPageUrl": "https://harbourplumbing.com.au/contact","hasContactForm": true,"emailSources": "info@harbourplumbing.com.au — https://harbourplumbing.com.au/contact (cloudflare); …","pagesVisited": 3,"chargedEvents": "website-checked; contacts-found"}
Every row is flat (no nested objects), so CSV and Excel exports have one column per value. Lists are joined with ; .
What it does NOT do (please read)
- No JavaScript rendering. Pages are read as the server sends them, which keeps the price low and the speed high. Sites built entirely in the browser (some Wix, Squarespace and React sites) may show few or no contacts. Those rows have
jsHeavy: trueso you can spot them. - Emails behind contact forms can't be found by any crawler. Many small businesses publish only a form. Those rows say
hasContactForm: trueand give you thecontactPageUrl. - At most 10 pages per site (5 by default): the homepage, then the most promising contact, impressum, about and team pages. Emails that only appear on deep pages such as blog posts or individual staff profiles may be missed.
- Polite by design: we follow robots.txt (
siteStatus: robots_disallowedwhen a site asks bots to stay out, free), read one page at a time per site with a pause, and honour crawl-delay up to 5 s. - No bypassing of protection. Sites behind Cloudflare challenges, captchas or logins are reported as
blocked(free). Facebook, Instagram, Linktree and similar pages are not read, because they need a login. - No email verification. We report what the website publishes. We don't ping mail servers (Apify blocks port 25), and an address on a website can still bounce.
- Phone numbers are only as good as the page. Numbers are validated with Google's libphonenumber rules. The country comes from the domain (
.com.au→ AU), the site's schema.org data, your Default country, or the page language, in that order. When none of these works (a.comsite with no hints), local numbers fromtel:links are shown as written (not converted to+…) and local numbers in plain text are skipped rather than guessed;notestells you to set Default country. - Redirects are followed. If
old-name.comredirects tonew-name.com, contacts come from the new site andnotessays so. Check those rows when you need contacts for the original company only.
How accurate is it?
We tested it on 43 real small-business websites (cafés, hairdressers, bakeries, dentists, bike shops, plumbers) taken from OpenStreetMap listings in Australia, Germany and the UK, in the Apify cloud with default settings (November 2026):
| Result | |
|---|---|
| Websites that could be read | 34 of 43 (79%). The other 9: 3 dead domains, 2 blocking bots (HTTP 403), 1 robots.txt opt-out, 1 expired certificate, 1 server error, 1 never answered. All 9 were free. |
| Read websites with at least one email or phone | 27 of 34 (79%): 23 with an email, 24 with a phone, 23 with a social profile, 25 with a contact page found |
| Read websites with nothing found | 7: 3 built entirely in JavaScript (no text without a browser), 3 offering only a contact form, 1 redirecting to an unrelated site |
| Manual check | We re-downloaded every page the Actor visited and compared every mailto:/tel: link and visible email by hand. None were missed and no addresses were made up. |
| Against OpenStreetMap's own email for the business | Same address found in 7 of 13 cases. The 6 misses: 1 JavaScript-only site, 1 blocked, 1 server error, and 3 where the address isn't on the pages of the website at all |
Expect similar numbers on local-business lists. Big corporate sites (Google, Amazon…) rarely publish an email and often block bots, so results there are much lower. Found emails are what the website shows; they are not verified as deliverable.
Site statuses
| siteStatus | Meaning | Charged |
|---|---|---|
ok | Homepage read | ✅ |
dead | The domain doesn't resolve (no website) | free |
unreachable | Timeout or connection refused | free |
tls_error | Broken HTTPS, and no plain-HTTP version | free |
http_error | The homepage returns an error (404, 500…) | free |
blocked | Bot protection, captcha, 401/403/429 | free |
parked | Domain-for-sale or placeholder page | free |
robots_disallowed | robots.txt asks bots not to read the homepage | free |
redirects_to_platform | The domain just forwards to Facebook, Instagram, a marketplace… | free |
not_html | The address serves a file, not a web page | free |
rowStatus is checked for all of the above, invalid_input for entries that aren't websites (free, with a reason), and not_processed for websites not started because your maximum cost per run was reached (free). Those, plus any websites skipped by maxWebsites, are listed in the REMAINING key-value record, ready to re-run.
Input options
| Field | Default | What it does |
|---|---|---|
websites | — | Websites, URLs or email addresses, one per line |
websitesFileUrl | — | Link to a CSV / TXT file or Google Sheet (up to 100,000 rows) |
maxPagesPerSite | 5 | 1–10 pages per website. The price stays the same; more pages are just slower |
defaultCountry | — | 2-letter code used to read local phone numbers when the site doesn't show its country |
maxWebsites | 0 (all) | Read only the first N, which is handy for a cheap trial on a big file |
maxConcurrency | 10 | Websites read in parallel |
pageTimeoutSecs | 30 | Per-page timeout; each website stops after 2 minutes in total |
selfTest | false | Run the built-in health check instead (free, no rows) |
Speed and limits
About 30–60 websites per minute with the defaults (measured: 60 websites in 87 seconds; 1,000 sites ≈ 20–30 minutes). Slow or dead hosts are the main factor; raising maxConcurrency to 20–30 roughly halves the time. The log shows an ETA and the maximum cost at the start. If you set a Maximum cost per run, the Actor stops cleanly when it's reached: finished rows are kept, the rest are marked not_processed (free), and the status message says how many are left. Websites already being read when the limit is hit are still delivered, free.
Bad input never fails the run. If nothing usable was given, the run ends with a clear message and $0 charged.
Good to combine with
- OpenStreetMap Business Leads: get local businesses with their websites, then feed the CSV link straight into this Actor.
- Domain Checker: check whether those domains have working email (MX, SPF, DMARC) before you email them.
Responsible use
This Actor only reads pages that are public and allowed by robots.txt. Business contact details are often still personal data (GDPR, Australian Privacy Act, CAN-SPAM). You are responsible for having a lawful basis to store and contact them, and for honouring opt-outs.
Support
Found a site where we missed a visible email or phone? Open an issue on the Issues tab with the URL. Bug reports are usually fixed within a few days.