Bulk WHOIS lookup : outils, scripts et méthodes API
Comment interroger WHOIS ou RDAP pour des dizaines de domaines à la fois. Outils web, script bash avec rate limiting et approche RDAP en Python.
Interroger WHOIS ou RDAP pour une liste de domaines n'est pas trivial. Le protocole WHOIS impose des limites de requêtes strictes par IP, les dépasser entraîne un blocage d'une heure ou plus. Le serveur varie selon le TLD, donc une liste de 100 domaines sur différentes extensions peut nécessiter d'interroger 20 serveurs différents. Et la sortie texte brut est difficile à parser de façon fiable. RDAP résout les deux derniers problèmes mais a ses propres limites. Cet article couvre trois approches dans l'ordre croissant de complexité : un outil web, un script bash avec rate limiting, et un script Python RDAP. Le bon choix dépend de votre volume et de si vous avez besoin des résultats une fois ou de façon continue.
Le problème du rate limiting
Avant de choisir une solution, comprendre pourquoi une simple boucle ne fonctionne pas :
- La plupart des serveurs WHOIS limitent à 1-5 requêtes par seconde par IP. Dépasser ça déclenche un blocage temporaire, typiquement 1 heure, parfois 24 heures.
- Il n'existe pas de standard pour définir comment un client bloqué doit se comporter. Certains serveurs retournent un message d'erreur ; d'autres cessent simplement de répondre.
- RDAP gère le rate limiting plus proprement : les serveurs retournent HTTP 429 avec un header
Retry-Afterindiquant exactement combien de temps attendre. Mais la limite existe quand même. - Une liste mêlant
.com,.net,.io,.fret.denécessite d'interroger cinq serveurs WHOIS différents, chacun avec ses propres limites.
La règle pratique : rester à 1 requête toutes les 2 secondes pour WHOIS, et respecter chaque réponse HTTP 429 des serveurs RDAP.
Rate limit atteint ? Les serveurs RDAP doivent retourner HTTP 429 avec un header Retry-After. Respectez-le, ou votre IP sera bannie.
Méthode 1: Outils web pour le bulk lookup
Pour les non-développeurs qui veulent uploader une liste et obtenir des résultats sans écrire de code :
| Outil | Limite gratuite | Format de sortie | Notes |
|---|---|---|---|
| WhoisXMLAPI | 500 crédits/mois | JSON, CSV | Bonne couverture API |
| ViewDNS.info | ~100/jour | HTML, CSV | Basique, pas d'API |
| DomainTools | Minimal | CSV, JSON | Le plus complet, cher |
| Who.is | Très limité | HTML uniquement | Manuel seulement |
La limite de tous ces outils : ils plafonnent les requêtes bulk à des volumes raisonnables en version gratuite, et le tarif monte vite au-delà de quelques centaines de domaines par mois. Ils conviennent pour des besoins ponctuels à volume modéré. Pour des volumes supérieurs à 500 domaines ou des besoins récurrents, un script est plus économique.
Méthode 2: Script bash avec rate limiting
Pour les utilisateurs Linux et macOS qui veulent une solution simple sans dépendances. Sauvegarder sous bulk-whois.sh :
#!/bin/bash
# bulk-whois.sh: interroger WHOIS pour une liste de domaines
# Usage : ./bulk-whois.sh domains.txt
DELAY=2 # secondes entre les requêtes, rester dans les limites
INPUT="$1"
if [[ -z "$INPUT" ]]; then
echo "Usage : $0 <fichier-domaines>"
exit 1
fi
while IFS= read -r domain; do
# ignorer les lignes vides et les commentaires
[[ -z "$domain" || "$domain" == \#* ]] && continue
echo "=== $domain ==="
whois "$domain" 2>/dev/null \
| grep -E "Registrar:|Expir|Name Server|Domain Status"
sleep "$DELAY"
done < "$INPUT"
Le filtre grep -E n'extrait que les lignes utiles, sans ça, la sortie WHOIS brute fait 50-100 lignes par domaine. Créer un fichier domains.txt avec un domaine par ligne :
github.com
stripe.com
# cette ligne est ignorée
vercel.com
netlify.com
Extraction vers CSV
Pour intégration avec des tableurs ou d'autres outils, voici une version qui écrit un CSV :
#!/bin/bash
OUTPUT="output.csv"
echo "domain,registrar,expiry,status" > "$OUTPUT"
while IFS= read -r domain; do
[[ -z "$domain" || "$domain" == \#* ]] && continue
raw=$(whois "$domain" 2>/dev/null)
registrar=$(echo "$raw" | grep -i "^Registrar:" \
| head -1 | cut -d: -f2- | xargs)
expiry=$(echo "$raw" | grep -iE "Expiry|Expiration Date" \
| head -1 | cut -d: -f2- | xargs)
status=$(echo "$raw" | grep -i "^Domain Status:" \
| head -1 | cut -d: -f2- | xargs)
echo "$domain,$registrar,$expiry,$status" | tee -a "$OUTPUT"
sleep 2
done < domains.txt
Un avertissement important : les noms de champs grep varient selon les registres. Expiry Date fonctionne pour Verisign ; Expiration Date est la forme retournée par certains registrars. Le pattern grep -iE "Expiry|Expiration Date" couvre les deux mais peut en manquer d'autres. C'est la fragilité fondamentale du parsing de texte WHOIS, c'est pour ça que RDAP a été créé.
Méthode 3: Requêtes RDAP via script
L'approche recommandée pour les développeurs. RDAP donne du JSON structuré, donc le parsing est fiable et les noms de champs sont constants quel que soit le registre qui répond.
Trouver le bon serveur RDAP par TLD
Le fichier bootstrap IANA associe les TLDs aux URLs des serveurs RDAP. Le récupérer une fois au démarrage :
import json
import urllib.request
import time
# Charger le bootstrap IANA une fois au démarrage
with urllib.request.urlopen("https://data.iana.org/rdap/dns.json") as r:
bootstrap = json.load(r)
def get_rdap_server(tld: str) -> str | None:
for entry in bootstrap["services"]:
if tld.lower() in [t.lower() for t in entry[0]]:
return entry[1][0]
return None
def rdap_lookup(domain: str) -> dict:
tld = domain.split(".")[-1]
server = get_rdap_server(tld)
if not server:
return {"error": f"Pas de serveur RDAP pour .{tld}"}
url = f"{server.rstrip('/')}/domain/{domain}"
try:
with urllib.request.urlopen(url, timeout=10) as r:
return json.load(r)
except urllib.error.HTTPError as e:
return {"error": f"HTTP {e.code}", "retry_after": e.headers.get("Retry-After")}
except Exception as e:
return {"error": str(e)}
domains = ["github.com", "stripe.com", "vercel.com", "netlify.com"]
for domain in domains:
data = rdap_lookup(domain)
if "error" in data:
print(f"{domain}: ERREUR, {data['error']}")
if data.get("retry_after"):
wait = int(data["retry_after"])
print(f" Rate limité. Attente {wait}s...")
time.sleep(wait)
continue
# Extraire la date d'expiration depuis le tableau events
expiry = next(
(e["eventDate"] for e in data.get("events", [])
if e["eventAction"] == "expiration"),
"N/A"
)
status = ", ".join(data.get("status", []))
print(f"{domain}: expire le {expiry} | statuts: {status}")
time.sleep(1) # 1 req/s, conservateur pour RDAP
Ce script est minimal. En production, ajouter un cache local du fichier bootstrap (il ne change que rarement), un backoff exponentiel sur les retry, et des logs. Le script ci-dessus écrit sur stdout ; rediriger vers un fichier ou passer par jq selon les besoins.
Utiliser l'API Domain Sentinel
Pour les workloads de production où vous ne voulez pas maintenir vous-même le bootstrapping RDAP, la logique de rate limiting et le fallback WHOIS, Domain Sentinel expose une API qui gère tout ça. Une seule requête authentifiée retourne des données structurées quelle que soit la façon dont le TLD est servi. Voir la documentation API Domain Sentinel pour les détails des endpoints et l'authentification.
Surveiller un portefeuille de domaines en continu
Il y a une distinction importante entre le bulk lookup et la surveillance continue :
Le bulk lookup donne un snapshot des données actuelles au moment de la requête. On l'exécute une fois, on obtient les résultats, on passe à autre chose.
La surveillance continue signifie vérifier chaque domaine régulièrement et recevoir une alerte quand quelque chose change, date d'expiration qui approche, nameservers qui changent, statut EPP qui évolue.
Le bulk lookup donne un snapshot. Domain Sentinel donne un flux continu avec des alertes.
Pour un portefeuille de 50 domaines répartis sur plusieurs entreprises ou clients, le workflow opérationnel est : importer la liste dans Domain Sentinel, configurer les seuils d'alerte (60 jours, 30 jours, 7 jours avant expiration), et recevoir des notifications par domaine plutôt que d'exécuter des scripts manuellement. Chaque changement détecté est enregistré avec un horodatage, ce qui constitue aussi une piste d'audit.
Le choix dépend du volume et de la fréquence : pour 10 à 50 domaines vérifiés ponctuellement, un outil web ou un script bash convient. Pour 50 à 500 domaines vérifiés régulièrement, le script Python RDAP est pratique. Pour 500 domaines et plus, ou tout portefeuille qui nécessite une surveillance continue plutôt que des vérifications ponctuelles, un service dédié est la bonne réponse.
Commencez par un domaine qui vous importe
Recherchez-le gratuitement. Pour recevoir des alertes sur les changements de statut ou l'expiration, créez un compte. Ça prend 30 secondes.