Audit contact details
Before a rebrand, a compliance review, or a directory sync, someone always has to answer the same question: what contact details are actually published on this page right now? This endpoint scans a URL and returns the emails, phone numbers and social profile links it finds in the rendered content, so that answer takes seconds instead of a manual read-through.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The problem: pages drift, records don't get updated
A contact page gets edited by three different people over two years, a phone number changes when the office moves, an old employee's email stays live in a footer nobody rereads. Teams responsible for accuracy, whether that's a legal or compliance reviewer, a webmaster doing a pre-launch audit, or an operations lead consolidating a company directory, need a reliable way to see what's actually on a page today rather than trusting what a spreadsheet from last year says, especially across dozens of location or franchise pages that nobody reviews on a fixed schedule.
What the endpoint returns
Submit a URL and get back a task_id; once processing finishes, a webhook or a signed link (valid 24 hours) delivers the structured list of contact signals found on the page: email addresses, phone numbers in whatever format they appear, and links to social profiles referenced in the markup. Results reflect exactly what's published, no guessing or enrichment from outside sources, so what you get back is a faithful snapshot of the page rather than an inferred or padded record.
Meant for auditing pages you're responsible for
This is a page-content extraction tool, not a people-lookup service: it reads what's already publicly displayed on a URL you provide, the same information any visitor to that page can already see. It's built for auditing your own site, a client's site under contract, or a partner's public page you need to verify, not for building unsolicited contact lists from third-party sites, and it won't infer or fabricate a detail that isn't literally present in the page's content.
Fitting into a recurring workflow
Because the call is async and priced per request, it slots naturally into a scheduled job: run it monthly across every location or team page on a site, diff the output against last month's, and flag anything that changed. That turns contact-info accuracy from a once-a-year fire drill into a quiet, automated check that runs in the background.
What you can do with it
Pre-launch site audits
Confirm every location page on a new site shows the correct phone number and email before the redesign goes live.
Compliance and privacy reviews
Check whether an old employee's personal email is still exposed on a public team page after they've left the company.
Directory consistency checks
Compare the contact details published on a franchise or branch page against the internal directory to catch drift.
Change monitoring after a migration
Re-scan pages after a CMS migration to confirm contact blocks survived the move intact and unbroken.
FAQ
How do I extract contact info from a website with this API?
Send a POST request to /web/contacts with the target URL; you receive a task_id immediately, and the extracted contact details arrive by webhook or a signed link once the task completes.
Is the contact extraction API free to use?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
What kind of contact data does it return?
It returns email addresses, phone numbers, and links to social profiles that are explicitly present in the page's rendered content.
Can this be used to scrape emails from other people's websites?
It reads only what is already publicly published on a URL you submit; it is designed for auditing pages you own or are responsible for, not for building outreach lists from third-party sites.
Does it work on pages that load contact details with JavaScript?
The page is rendered before extraction, so contact details injected dynamically by client-side scripts are captured along with the static markup.
How much does it cost to run in bulk?
Each request is billed at a flat $0.002, so running it across many pages scales linearly with the number of pages checked.
How do I get the results?
Choose a signed webhook for automatic delivery, or retrieve the output from a signed link that remains valid for 24 hours.
Is the extracted data retained afterward?
No, data is deleted once the retention window ends and is never used for training any model.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/web/contacts \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://ejemplo.com"}'const res = await fetch("https://api.kit.forhosting.com/web/contacts", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"url": "https://ejemplo.com"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/web/contacts",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"url": "https://ejemplo.com"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/web/contacts", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"url":"https://ejemplo.com"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"url":"https://ejemplo.com"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/web/contacts", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"url": "https://ejemplo.com"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "web.contacts",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
timeout_sec | 30 |
max_crawl_pages | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |