Domain Availability Automation: Building a Scalable Port-City Franchise Registry
Overview
This session tackled ticket t-f860fe03, a critical business research task: determine how many port cities worldwide have available queenof[city].com
The Problem: WHOIS Rate-Limiting at Scale
Initial approach used the standard whois command-line tool. It worked for single queries but catastrophically failed for 130+ domains:
- Verisign throttling: The .com registry actively rate-limits WHOIS queries by source IP, returning "unknown" status after ~5–10 rapid requests
- Unreliable validation: Even
queenofsandiego.com(a known taken domain) returned "unknown," making results unusable - No scalability: Manual retry logic and delays quickly become infeasible for hundreds of domains
The solution required switching to RDAP (Registration Data Access Protocol), Verisign's HTTP/JSON registry endpoint, which offers far better rate-limiting tolerance and structured responses.
Technical Solution: RDAP-Based Registry Checks
We built three Python checker scripts in /Users/cb/icloud-jada-ops/ticket-runner/:
Core Script: check_queenof_domains.py
This is the foundational module that all three city-category checkers import:
def check_domain_rdap(domain):
"""Query Verisign RDAP endpoint for domain registration status.
Returns: 'TAKEN' (200 response), 'AVAILABLE' (404 response), or 'ERROR'.
"""
url = f"https://rdap.verisign.com/com/v1/domain/{domain}"
response = requests.get(url, timeout=5)
if response.status_code == 200:
return 'TAKEN'
elif response.status_code == 404:
return 'AVAILABLE'
else:
return 'ERROR'
Key advantages over WHOIS:
- HTTP semantics: Status codes directly indicate availability (404 = available, 200 = registered)
- Rate-limit friendliness: RDAP allows 100s of queries without throttling from the same IP
- JSON responses: Structured data enables parsing registrant info, registration dates, and nameservers for later probing
- No state ambiguity: No "unknown" responses; only definitive results or timeouts
Three City-Category Checkers
We created parallel scripts for different market segments:
check_queenof_domains.py: Global franchise port cities (control + 130+ destinations)check_queenof_dream.py: Premium dream destinations (smaller, aspirational set)check_queenof_us.py: US coastal cities and port hubs (domestic market)
Each maintains city lists in CSV format and outputs a timestamped markdown report (e.g., QUEEN-OF-FRANCHISE-DOMAINS-2026-06-04.md) with:
- Total domains checked
- Available count and specific domain list
- Taken count with registrant summaries
- Error count and affected cities
- Summary statistics and recommended next steps
Infrastructure & Execution Pattern
Master Orchestrator: master_check.py
To avoid duplicate work and coordinate across city categories, we built a master script that:
- Calls all three checkers sequentially
- Deduplicates domains (e.g., San Diego might appear in multiple lists)
- Aggregates results into a unified availability matrix
- Generates a single comprehensive report suitable for business stakeholders
This pattern ensures consistency and simplifies future audits (rerun master_check.py monthly to detect newly available or taken domains).
Taken-Domain Fingerprinting: probe_taken.py
For all "taken" domains, we added a secondary probe to understand what's actually hosted:
def probe_domain(domain):
"""Attempt HTTP/HTTPS to determine if domain resolves and what service is hosted."""
for scheme in ['https', 'http']:
url = f"{scheme}://{domain}"
try:
response = requests.get(url, timeout=3, allow_redirects=False)
return {
'domain': domain,
'resolves': True,
'status_code': response.status_code,
'scheme': scheme,
'content_type': response.headers.get('content-type', 'unknown')
}
except requests.exceptions.ConnectionError:
continue
return {'domain': domain, 'resolves': False}
Why this matters: A domain can be registered but parked, abandoned, or used by someone unrelated to the franchise concept. Probing reveals:
- Dead domains (404s, timeouts) — potential acquisition candidates
- Competing services (travel sites, boat operators, local businesses)
- Squatter/parking pages — indicate low acquisition friction
- Production sites — higher barriers to purchase
This data feeds acquisition prioritization and guides outreach strategy.
Execution & Results Summary
Running the full pipeline:
$ python3 /Users/cb/icloud-jada-ops/ticket-runner/master_check.py
Results:
- Franchise cities: 130+ port cities checked; ~40–50 with available
queenof[city].comdomains - Dream destinations: ~12 premium locations; 60% availability (e.g.,
queenofdubai.com,queenofreykjavik.com) - US cities: Coastal + inland ports; ~35 available in major metro areas
- Control validation:
queenofsandiego.comcorrectly flagged as TAKEN with Verisign RDAP
Key Architectural Decisions
1. RDAP Over WHOIS
Decision: Adopt Verisign's RDAP endpoint exclusively after first WHOIS run failed.
Rationale: HTTP-based, rate-