DNS lookup
A migration, a broken email flow, or a mysterious 'domain not found' almost always traces back to one DNS record that's wrong, missing or still propagating from three providers ago. This endpoint queries every major record type for a domain in a single call and hands them back as structured data, turning a scavenger hunt across dig, nslookup and three browser tabs into one request.
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.
DNS: simple in theory, tangled in practice
The Domain Name System has quietly run the internet's addressing since the 1980s, translating names into the addresses machines actually use, and the record types haven't changed all that much since — A and AAAA for addresses, MX for mail, TXT for the endless list of verification and policy strings modern services demand, NS for delegation, CNAME for aliasing, SOA for zone authority. What's changed is how many of these records a single domain now needs, especially with SPF, DKIM and DMARC all living in TXT records that are easy to misconfigure.
One call, every record type that matters
POST /web/dns with a domain name and, optionally, which record types you want (or leave it open to get all of A, AAAA, MX, TXT, NS, CNAME and SOA at once). The task resolves each type and returns them as clean structured JSON, so you're not shelling out to a command-line tool and scraping its output, or making seven separate calls to seven separate lookup services.
The debugging moments this actually saves
Email suddenly bouncing after a provider switch is almost always an MX or SPF/TXT mismatch; a site that resolves for some visitors but not others is often a stale NS delegation still pointing at an old provider; a CNAME that silently breaks a subdomain is often the first thing anyone checks once they suspect DNS. Having every record type in one response means you compare what's live against what should be live in seconds instead of piecing it together from several tools with different output formats.
Built to run unattended
Because the task is asynchronous with webhook delivery, it's a natural fit for a migration checklist that verifies records post-cutover, a monitoring job that alerts if an MX record ever changes unexpectedly, or a customer-onboarding flow that checks a client's DNS is correctly pointed before provisioning anything on your side. No need to poll — the result lands when it's ready, or waits for you at a signed link for 24 hours.
Pricing built for frequent checks
At $0.002 per request, checking DNS across a whole domain portfolio on a schedule is inexpensive enough to run daily without a second thought. Failed tasks are retried automatically up to three times and never charged, so the only thing you pay for is a lookup that actually completed.
What you can do with it
Post-migration DNS verification
After moving a domain to a new DNS provider, a team checks all record types at once to confirm nothing was dropped in the transfer.
Email deliverability troubleshooting
A support engineer pulls MX and TXT records together to spot a missing SPF entry that's causing outbound mail to land in spam.
Client onboarding checks
A hosting reseller verifies a new client's nameservers and A records point correctly before activating their account.
Change monitoring
A company schedules a daily DNS check on its own domains to get alerted the moment an MX or NS record changes unexpectedly, a common early sign of a compromised registrar account.
FAQ
Which record types does the DNS lookup API return?
A, AAAA, MX, TXT, NS, CNAME and SOA, either all at once or filtered to the specific types you request.
Can I check just one record type, like MX?
Yes, you can request a specific record type or leave it open to get the full set in a single call.
How is this different from running dig or nslookup?
Same underlying resolution, but delivered as structured JSON via webhook instead of terminal text you have to parse, and it covers multiple record types in one request.
Is there a free tier?
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.
How current are the results?
The task performs a live resolution at request time, reflecting what's currently published, though propagation delays after a recent DNS change are outside our control.
Am I charged if a domain has no record of a given type?
Yes, an empty result for a specific type is still valid, useful information and is billed normally. Only tasks that fail to run on our end are retried free of charge.
Can I use this to monitor DNS changes over time?
Yes, scheduling repeated checks and diffing the results is a common pattern for catching unexpected MX or NS changes early.
Can I look up many domains at once?
Each call covers one domain across all requested record types; running it across a list on a schedule is straightforward and stays cheap at $0.002 per request.
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/dns \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"domain":"ejemplo.com"}'const res = await fetch("https://api.kit.forhosting.com/web/dns", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"domain": "ejemplo.com"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/web/dns",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"domain": "ejemplo.com"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/web/dns", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"domain":"ejemplo.com"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"domain":"ejemplo.com"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/web/dns", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"domain": "ejemplo.com"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "web.dns",
"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. |