Domain Availability Research at Scale: Building a Port-City Franchise Validator with RDAP and Python
What Was Done
Ticket t-f860fe03 requested research into domain availability for a "Queen of [City]" franchise concept—a distributed tour operator business model where each port city could register queenof[city].com as a branded local entity. The challenge: determine how many of ~130 port cities worldwide have available domains, and do so reliably and at scale.
Over this session, we built and deployed three independent domain checkers (check_queenof_domains.py, check_queenof_dream.py, check_queenof_us.py), a master coordinator (master_check.py), and a hosting probe (probe_taken.py) to answer the research question and validate infrastructure assumptions.
The WHOIS Problem and Why We Switched to RDAP
Initial approach used the whois command-line tool via Python subprocess. This failed catastrophically:
- Rate limiting: Verisign (the .com registry) throttles
whoisqueries by source IP. After ~20 queries, responses became "unknown" rather than authoritative. - Unreliability: Even known-taken domains like
queenofsandiego.comreturned "unknown" under load, making results untrustworthy for reporting. - No programmatic structure: WHOIS returns free-form text requiring fragile regex parsing.
Solution: RDAP (Registration Data Access Protocol). Verisign operates a public RDAP endpoint at https://rdap.verisign.com/com/v1/domain/ which:
- Returns structured JSON (no parsing fragility).
- Uses HTTP caching and is far less throttled than WHOIS.
- Provides authoritative answers:
404 = available,200 = registered. - Supports bulk queries without IP-level rate limiting.
Architecture: Three Parallel Checkers + Master Coordinator
Rather than a single monolithic checker, we built a three-domain-list architecture:
/Users/cb/icloud-jada-ops/ticket-runner/check_queenof_domains.py— Top-12 port cities (San Diego, Singapore, Dubai, Hong Kong, etc.). This became the primary validation target.check_queenof_dream.py— Dream destinations (Barcelona, Bora Bora, Santorini, etc.) — aesthetic/lifestyle focus.check_queenof_us.py— US-only cities (Miami, New York, Los Angeles, etc.) — domestic market potential.
Each checker generates a timestamped markdown report (QUEEN-OF-*.md) with results, counts, and available domains listed for action.
master_check.py coordinates all three, runs them sequentially, and aggregates results into a single decision artifact.
Implementation: RDAP Query Logic
Core pattern (pseudo-code; actual implementation in check_queenof_domains.py):
import requests
RDAP_ENDPOINT = "https://rdap.verisign.com/com/v1/domain/"
def check_domain(domain):
try:
response = requests.get(f"{RDAP_ENDPOINT}{domain}", timeout=5)
if response.status_code == 404:
return "AVAILABLE"
elif response.status_code == 200:
return "TAKEN"
else:
return "UNKNOWN"
except requests.RequestException:
return "ERROR"
Key decisions:
- Timeout of 5 seconds: RDAP is fast; anything slower likely indicates network issues.
- Status codes as source of truth: We ignore response body for the availability determination; the HTTP status code is definitive.
- Batching with short delays: To avoid any appearance of DOS, we added 0.5-second delays between queries even though RDAP doesn't rate-limit per-IP.
- Retry logic: Transient timeouts retry once before marking as ERROR.
Validation: The Control Domain
We included queenofsandiego.com as a known-taken control. When WHOIS failed to identify it as taken, we knew we had a problem. When RDAP correctly returned 200 (TAKEN) for that domain, it validated the entire approach.
This is a critical QA pattern: always include a known-good and known-bad sample in bulk registry queries.
Hosting Probe: What's Actually Running?
probe_taken.py follows up on the registered domains: it performs HTTP/HTTPS requests to each "TAKEN" domain to determine:
- Is it parked? (typical registrar landing page)
- Does it redirect? (to what domain/service?)
- Is it active? (200 response with actual content)
- What IP/CDN is serving it?
This uncovers opportunities: a domain registered but parked (no active service) might be purchasable. A domain in active use by a competitor needs different strategy.
Reporting and Integration
Each checker writes results to a timestamped markdown file:
QUEEN-OF-FRANCHISE-DOMAINS-2026-06-04.md(Top-12 cities)QUEEN-OF-DREAM-DESTINATIONS-2026-06-04.md(Dream cities)QUEEN-OF-US-CITIES-2026-06-04.md(US cities)
Format includes:
- Summary counts: Total queried, available, taken, errors.
- Available domains list: Actionable inventory for franchise expansion.
- Taken domains list: For competitor/adjacent research.
- Metadata: Run timestamp, RDAP endpoint version, timeout settings.
Key Decisions: Why This Architecture?
- Separate checkers instead of one monolith: Allows independent scheduling, different retry logic for different city lists, and cleaner git history for domain list changes.
- RDAP over WHOIS: Structured data, HTTP (cacheable), less rate-limited, and no parsing fragility.
- Markdown reports instead of JSON: Human-readable, git-friendly, embeddable in tickets and documentation.