#cybersecurity
#bugbounty
#aiagents
#pentesting
#whois
#subdomaintakeover
#rapidapi
#nightcrawler
A few days ago a Show HN project called Nightcrawler caught my attention: a local AI pentesting agent that runs entirely on a smartphone. The idea is compelling — carry an offensive-security assistant in your pocket, no cloud GPU required. But local LLMs on a phone are compute-starved. They cannot brute-force subdomains, resolve thousands of DNS records, or pull historical WHOIS/RDAP snapshots without draining the battery and burning through mobile data.
That is exactly where a lightweight reconnaissance API shines. If Nightcrawler wants to map an attack surface, it should not do the heavy lifting itself. It should call a backend that already knows how to:
The Domain WHOIS API bundles all of that into one request. In this article I’ll show you how to turn that API into a reconnaissance backend that a phone-based agent like Nightcrawler can use to flag subdomain takeover risks in seconds.
Subdomain takeover is one of the highest-impact, lowest-complexity bugs in bug bounty programs. An attacker finds a dangling DNS record — for example docs.example.com
still pointing to a GitHub Pages or Heroku app that no longer exists — and claims it. The fix is usually just deleting the DNS record, but finding the dangling records at scale is the hard part.
A smartphone agent cannot run amass
, subfinder
, and dnsx
pipelines locally without melting the SoC. Instead, it can ask:
“API, here is a target domain. Give me subdomains, their DNS resolution status, any dangling CNAMEs, and a takeover-risk score.”
Then the local LLM simply reasons over the structured JSON response and decides whether to escalate the finding to the user.
The Domain WHOIS API response is a single JSON document that combines several recon tools. A typical payload looks like this:
{
"domain": "example.com",
"rdap": {
"registrar": "Example Registrar, Inc.",
"creation_date": "1995-08-14",
"expiration_date": "2025-08-13",
"name_servers": ["ns1.example.com", "ns2.example.com"]
},
"dns": {
"A": ["93.184.216.34"],
"AAAA": ["2606:2800:220:1::"],
"MX": ["mail.example.com"],
"TXT": ["v=spf1 include:_spf.example.com ~all"],
"NS": ["ns1.example.com"]
},
"ssl": {
"issuer": "DigiCert Inc",
"subject": "CN=example.com",
"not_after": "2025-01-15"
},
"subdomains": [
"www.example.com",
"mail.example.com",
"docs.example.com",
"staging.example.com"
],
"takeover_risk": {
"score": 7.2,
"dangling_cnames": [
{
"subdomain": "docs.example.com",
"cname": "example.github.io",
"status": "unregistered"
}
]
},
"email_security": {
"spf": "pass",
"dmarc": "pass",
"dkim": "neutral",
"dnssec": "signed",
"mta_sts": "missing",
"score": 82
}
}
With that one response, an agent can:
Below is a small Python helper that any local agent can embed. It queries the API, extracts high-risk subdomains, and prints a markdown report that the LLM can consume.
import os
import requests
RAPIDAPI_KEY = os.environ["RAPIDAPI_KEY"]
API_HOST = "domain-whois2.p.rapidapi.com"
BASE_URL = f"https://{API_HOST}"
def whois_recon(domain: str) -> dict:
url = f"{BASE_URL}/whois/{domain}"
headers = {
"X-RapidAPI-Key": RAPIDAPI_KEY,
"X-RapidAPI-Host": API_HOST,
}
resp = requests.get(url, headers=headers, timeout=45)
resp.raise_for_status()
return resp.json()
def takeover_report(domain: str) -> str:
data = whois_recon(domain)
risk = data.get("takeover_risk", {})
dangling = risk.get("dangling_cnames", [])
email = data.get("email_security", {})
lines = [f"# Recon report for `{domain}`\n"]
lines.append(f"- **Domain age:** {data.get('rdap', {}).get('creation_date')}")
lines.append(f"- **Takeover risk score:** {risk.get('score', 'N/A')}")
lines.append(f"- **Email security score:** {email.get('score', 'N/A')}\n")
if dangling:
lines.append("## 🚨 Potential subdomain takeovers")
for item in dangling:
lines.append(
f"- `{item['subdomain']}` → CNAME `{item['cname']}` ({item['status']})"
)
else:
lines.append("No dangling CNAMEs detected.")
return "\n".join(lines)
if __name__ == "__main__":
print(takeover_report("example.com"))
The report is intentionally markdown-shaped so a local LLM can parse it as tool output and decide whether to recommend further exploitation steps (always inside a legal, authorized scope).
If Nightcrawler is given a list of in-scope domains, it can parallelize reconnaissance without running any local DNS tooling:
from concurrent.futures import ThreadPoolExecutor
TARGETS = [
"example.com",
"acme.org",
"bugbounty-target.io",
]
def scan_domain(domain: str):
try:
data = whois_recon(domain)
risk = data.get("takeover_risk", {}).get("score", 0)
if risk and risk >= 6.0:
return {
"domain": domain,
"risk_score": risk,
"dangling": data.get("takeover_risk", {}).get("dangling_cnames", []),
}
except requests.RequestException as exc:
return {"domain": domain, "error": str(exc)}
return None
with ThreadPoolExecutor(max_workers=5) as pool:
results = pool.map(scan_domain, TARGETS)
for r in results:
if r:
print(r)
This keeps the phone’s workload tiny: one HTTP request per domain, then pure decision logic on the device.
/history
superpower
One of the most useful features for an AI pentester is the ability to see how a target changed over time. The /history/{domain}
endpoint returns historical snapshots of email-security records and subdomains, which is perfect for detecting infrastructure drift.
def history_recon(domain: str) -> dict:
url = f"{BASE_URL}/history/{domain}"
headers = {
"X-RapidAPI-Key": RAPIDAPI_KEY,
"X-RapidAPI-Host": API_HOST,
}
resp = requests.get(url, headers=headers, timeout=45)
resp.raise_for_status()
return resp.json()
history = history_recon("example.com")
print(history.get("subdomain_snapshots", [])[:3])
If docs.example.com
existed three months ago, disappeared from DNS yesterday, but its CNAME is still live, that is a prime takeover candidate.
The API is hosted on RapidAPI. Sign up, subscribe, and grab your key from the dashboard:
👉 Domain WHOIS API on RapidAPI: https://rapidapi.com/On13uka/api/domain-whois2
curl --request GET \
--url 'https://domain-whois2.p.rapidapi.com/whois/example.com' \
--header 'X-RapidAPI-Key: YOUR_RAPIDAPI_KEY' \
--header 'X-RapidAPI-Host: domain-whois2.p.rapidapi.com'
python
import requests
url = "https://domain-whois2.p.rapidapi.com/whois/example.com"
headers = {
"X-RapidAPI-Key": "YOUR_RAPIDAPI_KEY",
"X-RapidAPI-Host": "domain-whois2.p.rapidapi.com",
}
response = requests.get(url, headers=headers)
print(response.json())
Replace YOUR_RAPIDAPI_KEY
with the key from your RapidAPI dashboard. The exact endpoint paths (/whois/{domain}
, /history/{domain}
) are documented in the RapidAPI console, so check there for the latest route definitions and rate-limit details.
If you want to self-host a thin proxy, contribute improvements, or just inspect the implementation, the project is open source:
👉 GitHub repository: https://github.com/On13uka/domain-whois-api
You can fork it, add your own scoring logic, or build a FastAPI shim that Nightcrawler talks to over your private network.
Local AI pentesting agents like Nightcrawler are a fascinating shift: intelligence stays on the device, but raw reconnaissance does not have to. By off WHOIS/RDAP, DNS, SSL, subdomain discovery, takeover risk, and email-security scoring to the Domain WHOIS API, a smartphone agent can map attack surfaces in seconds without draining the battery or hammering mobile networks.
If you are building a phone-based security agent, bug-bounty automation, or a threat-intel dashboard, plug this API in as your reconnaissance layer. Your local LLM gets clean, structured data; your phone stays cool; and you get to focus on the actual exploitation logic — inside authorized scopes, of course.
Happy hacking, and may your subdomains never dangle.