API publique
API WHOIS & DNS de WhoIsLookup.ma
Quatre endpoints JSON en lecture seule : WHOIS d’un domaine, lookup DNS, propagation multi-résolveurs et audit SPF/DKIM/DMARC. Sans clé, sans inscription, CORS ouvert.
Démarrer
Toutes les URLs sont préfixées par https://whoislookup.ma et répondent en application/json; charset=utf-8. Seule la méthode GET est exposée.
curl https://whoislookup.ma/api/v1/whois/google.ma Versionnement. Les anciennes URLs (/api/whois/…,
/api/dns/…) restent servies indéfiniment et à l’identique : aucune
intégration existante n’est à modifier. Les nouvelles intégrations sont invitées à
utiliser /api/v1/…, où les évolutions futures seront publiées sans rupture.
WHOIS d’un domaine
GET /api/v1/whois/{domaine}
Enregistrement complet d’un domaine : disponibilité, registrar, statuts EPP, dates, serveurs de noms et contacts publiés par le registre. Les domaines .ma sont interrogés en WHOIS TCP auprès de whois.registre.ma (ANRT) ; les autres extensions passent par RDAP.
Paramètres
| Paramètre | Obligation | Description |
|---|---|---|
{domaine} | requis | Segment d’URL. Accepte une forme brute (WWW.Google.MA., https://google.ma/page) : la normalisation retire le protocole, le www. et le point final. |
fresh | optionnel | fresh=1 ignore le cache et interroge le registre directement. À réserver aux cas où la fraîcheur à la seconde compte (vérification avant une opération de registrar) : chaque appel est une requête réelle vers le registre. |
Exemple
curl https://whoislookup.ma/api/v1/whois/google.ma
Réponse
{
"domain": "google.ma",
"tld": "ma",
"availability": "registered",
"source": "whois",
"status": [
"clientTransferProhibited https://icann.org/epp#clientTransferProhibited"
],
"events": {
"registration": "2009-03-24T00:00:00.000Z",
"expiration": "2027-03-24T00:00:00.000Z",
"lastChanged": "2026-02-23T16:56:22.000Z"
},
"nameservers": [
"ns1.google.com",
"ns2.google.com",
"ns3.google.com",
"ns4.google.com"
],
"registrar": { "name": "GENIOUS COMMUNICATIONS" },
"registrant": { "name": "Google LLC" },
"admin": { "name": "…", "email": "…", "phone": "…" },
"technical": { "name": "…", "email": "…", "phone": "…" },
"fetchedAt": "2026-08-14T03:56:30.596Z",
"cached": true,
"cacheAgeSec": 312
}
Lookup DNS
GET /api/v1/dns/lookup
Résolution d’un type d’enregistrement via DNS-over-HTTPS chez Cloudflare (1.1.1.1). Réponse normalisée : le type numérique est traduit, le TTL et le code de statut sont exposés tels quels.
Paramètres
| Paramètre | Obligation | Description |
|---|---|---|
domain | requis | Nom de domaine à résoudre. |
type | optionnel | Type d’enregistrement — A (défaut), AAAA, MX, TXT, CNAME, NS, SOA, CAA, SRV. Un type hors liste renvoie 400. |
Exemple
curl 'https://whoislookup.ma/api/v1/dns/lookup?domain=google.ma&type=A'
Réponse
{
"domain": "google.ma",
"type": "A",
"resolver": {
"id": "cloudflare",
"label": "Cloudflare (1.1.1.1)",
"location": "Anycast global",
"url": "https://cloudflare-dns.com/dns-query"
},
"status": 0,
"statusLabel": "NOERROR",
"authenticated": false,
"truncated": false,
"durationMs": 27,
"answers": [
{ "name": "google.ma", "type": "A", "ttl": 293, "data": "142.251.127.103" },
{ "name": "google.ma", "type": "A", "ttl": 293, "data": "142.251.127.104" }
],
"authority": [],
"comment": null
}
Propagation DNS
GET /api/v1/dns/propagation
Même requête envoyée en parallèle à 4 résolveurs publics (Cloudflare, Google, AdGuard, NextDNS). distinctAnswerSets vaut 1 quand tout le monde répond la même chose ; propagated en est le raccourci booléen. fingerprint permet de regrouper les résolveurs qui s’accordent.
Paramètres
| Paramètre | Obligation | Description |
|---|---|---|
domain | requis | Nom de domaine à résoudre. |
type | optionnel | Même liste de types que le lookup. A par défaut. |
Exemple
curl 'https://whoislookup.ma/api/v1/dns/propagation?domain=nindohost.ma&type=NS'
Réponse
{
"domain": "nindohost.ma",
"type": "NS",
"totalResolvers": 4,
"successfulCount": 4,
"distinctAnswerSets": 1,
"propagated": true,
"results": [
{
"resolver": { "id": "cloudflare", "label": "Cloudflare (1.1.1.1)", "…": "…" },
"ok": true,
"error": null,
"status": 0,
"statusLabel": "NOERROR",
"durationMs": 46,
"answers": [
{ "name": "nindohost.ma", "type": "NS", "ttl": 86400, "data": "lily.ns.cloudflare.com." }
],
"fingerprint": "NS|lily.ns.cloudflare.com.;NS|matt.ns.cloudflare.com."
}
]
}
Authentification e-mail (SPF / DKIM / DMARC)
GET /api/v1/dns/email-auth
Audit complet de la configuration anti-usurpation d’un domaine : enregistrement SPF et ses mécanismes, politique DMARC, sélecteurs DKIM trouvés, plus un score sur 100 et des constats classés ok / warn / error.
Paramètres
| Paramètre | Obligation | Description |
|---|---|---|
domain | requis | Domaine à auditer. |
selectors | optionnel | Liste de sélecteurs DKIM séparés par des virgules, en remplacement de la liste courante testée par défaut. Entre 1 et 40 ; caractères autorisés A-Za-z0-9_-. |
Exemple
curl 'https://whoislookup.ma/api/v1/dns/email-auth?domain=google.ma&selectors=google,default'
Réponse
{
"domain": "google.ma",
"spf": {
"found": true,
"raw": "v=spf1 -all",
"mechanisms": ["-all"],
"qualifierForAll": "-",
"hasMultipleRecords": false,
"findings": [{ "level": "ok", "message": "SPF strict (`-all`) — bonne pratique." }]
},
"dmarc": {
"found": true,
"raw": "v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com",
"policy": "reject",
"subdomainPolicy": null,
"pct": 100,
"rua": ["mailto:mailauth-reports@google.com"],
"ruf": [],
"adkim": "r",
"aspf": "r",
"findings": [{ "level": "ok", "message": "Politique stricte `p=reject`…" }]
},
"dkim": {
"testedSelectors": ["google", "default"],
"results": [{ "selector": "google", "found": false, "raw": null, "keyType": null }],
"matched": [],
"findings": [{ "level": "warn", "message": "Aucun sélecteur DKIM courant trouvé…" }]
},
"score": { "value": 75, "max": 100, "grade": "B", "summary": "Bonne base…" }
}
Disponibilité d’un domaine
GET /api/v1/availability/{domaine}
Projection minimale du WHOIS quand seule la question « ce domaine est-il libre, et jusqu’à quand » compte. Même source et même cache que l’endpoint WHOIS, réponse dix fois plus petite. status reprend la valeur exacte du WHOIS : available, registered, unknown — ou error, auquel cas la réponse porte code et message au lieu des autres champs, avec le statut HTTP correspondant.
Paramètres
| Paramètre | Obligation | Description |
|---|---|---|
{domaine} | requis | Même normalisation que l’endpoint WHOIS. |
fresh | optionnel | fresh=1 ignore le cache. |
Exemple
curl https://whoislookup.ma/api/v1/availability/nindohost.ma
Réponse
{
"domain": "nindohost.ma",
"status": "registered",
"expiresAt": "2028-03-04T18:26:10.000Z",
"registrar": "NINDO HOST",
"cached": true
}
Disponibilité groupée (accès sur demande)
POST /api/v1/availability
Jusqu’à 20 domaines en une requête. Le statut HTTP global reste 200 même si certains domaines échouent : l’erreur est portée par l’item concerné, pas par le lot. Au-delà de 20 domaines, la requête est refusée avec un 413. Cet endpoint exige un en-tête x-api-key : un lot non caché ouvre autant de connexions simultanées vers le registre, ce qui n’est pas quelque chose que l’on ouvre à tout le monde.
Paramètres
| Paramètre | Obligation | Description |
|---|---|---|
x-api-key | en-tête, requis | Clé interne. Sans elle, la réponse est 401. |
domains | corps JSON, requis | Tableau de 1 à 20 noms de domaine : {"domains": ["a.ma", "b.ma"]}. |
Exemple
curl -X POST https://whoislookup.ma/api/v1/availability \
-H 'x-api-key: <votre clé>' \
-H 'content-type: application/json' \
-d '{"domains": ["nindohost.ma", "libre-probablement.ma"]}'
Réponse
{
"results": [
{
"domain": "nindohost.ma",
"status": "registered",
"expiresAt": "2028-03-04T18:26:10.000Z",
"registrar": "NINDO HOST",
"cached": true
},
{
"domain": "libre-probablement.ma",
"status": "available",
"expiresAt": null,
"registrar": null,
"cached": false
}
]
}
État des dépendances
GET /api/v1/health
Sonde destinée à un moniteur externe. 200 quand les dépendances amont répondent, 503 dès que l’une d’elles est en panne — utile pour distinguer « le site est cassé » de « une source de données est indisponible ». Le WHOIS .ma n’est volontairement pas sondé : chaque sonde serait une vraie requête au registre, et un moniteur à la minute deviendrait lui-même la charge dont on cherche à le protéger. Le champ notMonitored le rappelle explicitement.
Exemple
curl -i https://whoislookup.ma/api/v1/health
Réponse
{
"ok": true,
"checks": {
"doh_cloudflare": { "ok": true, "ms": 35 },
"rdap_org": { "ok": true, "ms": 36 }
},
"notMonitored": ["whois_registre_ma"],
"ts": "2026-08-14T04:14:34.613Z"
}
Codes d’erreur
L’endpoint WHOIS renvoie une charge d’erreur structurée et le statut HTTP correspondant :
{ "error": true, "code": "invalid_domain", "message": "Nom de domaine invalide.", "domain": "pas-un-domaine" } | HTTP | code | Signification |
|---|---|---|
400 | invalid_domain | Le domaine n’est pas analysable (syntaxe, longueur, label vide). |
422 | unsupported_tld | Aucun serveur WHOIS/RDAP connu pour cette extension. |
429 | rate_limited | Le registre amont a limité nos requêtes. Réessayer plus tard. |
502 | upstream_error | Le registre a répondu une erreur ou une réponse illisible. |
504 | timeout | Le registre n’a pas répondu dans le délai imparti. |
500 | internal_error | Erreur inattendue de notre côté. |
Les endpoints DNS suivent une convention plus simple : 400 pour un paramètre invalide,
502 lorsqu’un résolveur amont échoue, avec un corps { "error": "message en français" }.
Limites d’usage
| Portée | Limite | Dépassement |
|---|---|---|
Tous les chemins /api/, par IP | 60 requêtes / minute | 429 pendant 60 s, avec Retry-After: 60 |
| Salve courte, par IP | 10 requêtes / 10 secondes | Vérification anti-robot |
Ces seuils sont volontairement larges : les opérateurs mobiles marocains partagent leurs
adresses IP entre de nombreux abonnés, une limite serrée pénaliserait des utilisateurs
légitimes. Respectez le Retry-After plutôt que de retenter immédiatement.
Les intégrations internes Nindohost s’authentifient par un en-tête x-api-key qui
les exempte de ces limites — leurs réponses portent alors x-ratelimit-bypass: 1. Pour un accès de ce type, écrivez à contact@nindohost.ma en décrivant votre usage.
Usage équitable
Au-delà des limites techniques, deux règles de bon voisinage :
- Respectez le cache. Une réponse WHOIS reste valable plusieurs heures en pratique ; ne redemandez pas le même domaine en boucle.
- Ne saturez pas le registre.
whois.registre.maest l’infrastructure publique de l’ANRT. Un scraping massif de domaines.manous ferait bannir — et couperait le service pour tout le monde.
Besoin d’un volume soutenu, d’un traitement par lots ou d’un SLA ? Écrivez à contact@nindohost.ma.
Questions fréquentes
- L’API nécessite-t-elle une clé ou une inscription ?
- Non. Tous les endpoints documentés ici sont publics, en lecture seule, sans clé et sans inscription. Le CORS est ouvert (`Access-Control-Allow-Origin: *`), l’API est donc appelable directement depuis un navigateur.
- Quelles extensions de domaine sont couvertes ?
- Les domaines .ma sont interrogés directement auprès du registre marocain (ANRT) en WHOIS TCP. Toutes les extensions couvertes par RDAP (.com, .net, .org, .fr et la plupart des gTLD) passent par le protocole RDAP. Une extension sans serveur connu renvoie une erreur 422 unsupported_tld.
- Les réponses sont-elles mises en cache ?
- À deux niveaux. Côté HTTP, chaque réponse porte un en-tête Cache-Control : 60 secondes navigateur et 300 secondes CDN pour le WHOIS, 30 et 120 secondes pour les endpoints DNS. Côté serveur, les résultats WHOIS sont conservés 6 heures pour un domaine enregistré et 15 minutes pour un domaine disponible ; la réponse indique alors cached: true et cacheAgeSec, l’âge de la donnée en secondes. Ce cache existe pour ne pas saturer le registre marocain, qui est une infrastructure publique.
- Comment forcer une donnée WHOIS fraîche ?
- En ajoutant fresh=1 à l’URL de l’endpoint WHOIS. La réponse est alors lue directement auprès du registre et porte cached: false. À n’utiliser que lorsque la fraîcheur à la seconde est nécessaire : chaque appel avec fresh=1 est une requête réelle vers le registre. Les erreurs ne sont jamais mises en cache — un échec est toujours retenté auprès du registre au coup suivant.
- Que deviennent les URLs sans /v1 ?
- Elles restent en place indéfiniment. Les routes /api/v1/… sont des alias exacts du même code : même corps de réponse, mêmes codes HTTP. Le versionnement sert uniquement à pouvoir faire évoluer l’API plus tard sans casser les intégrations existantes.
- Y a-t-il une limite d’usage ?
- Oui : 60 requêtes par minute et par adresse IP sur l’ensemble des chemins /api/. Au-delà, les requêtes reçoivent un statut 429 accompagné d’un en-tête Retry-After indiquant le délai avant de réessayer. Une salve très rapide (plus de 10 requêtes en 10 secondes) peut aussi déclencher une vérification anti-robot. Pour un volume soutenu ou un traitement par lots, écrivez à contact@nindohost.ma.