> For the complete documentation index see https://domscan.net/llms.txt. Markdown versions of every docs page are available by appending .md to the page URL.

Source: https://domscan.net/fr/docs/subdomains

# Chercheur de Sous-domaines

Consultez la documentation de l'API Chercheur de Sous-domaines, ses paramètres de requête, les champs de réponse, les exemples de code et la gestion des erreurs pour les intégrations DomScan.

Non. Il s’agit d’une couverture passive au mieux. Les noms internes et les hôtes publics absents des jeux de données des sources n’apparaîtront pas, et la vérification DNS ne recherche aucun nom supplémentaire.

Utilisez GET /v1/subdomains?domain=example.com&sources=ct. La valeur ct sélectionne le pipeline de compatibilité, tandis que chaque entrée indique sa source réelle. Les échecs en mode cache uniquement renvoient 202 et les échecs de toutes les sources renvoient 503. Les crédits sont remboursés dans les deux cas.

GET /v1/subdomains

#### Paramètres de requête

| Paramètre | Type | Description |
| --- | --- | --- |
| domain requis | string | Domaine racine pour lequel trouver les sous-domaines (par exemple, "github.com") |
| prefer_cache optionnel | boolean token | Sert uniquement les résultats en cache. Si aucun cache frais ou ancien n’existe, l’API renvoie 202, lance une actualisation en arrière-plan et rembourse les crédits de la requête. Valeurs acceptées: true, false, 1, 0, yes et no. Valeur par défaut: false. |
| sources optionnel | string | Sélecteur de compatibilité. Seul `ct` est accepté. Il lance le pipeline de découverte passive, mais chaque résultat indique le fournisseur de l’indice: `crtsh`, `crtname`, `hackertarget`, `threatminer`, `wayback` ou `certspotter`. Les anciennes entrées en cache peuvent indiquer `ct`. |
| verify optionnel | boolean token | Vérifie par DNS uniquement les noms déjà sélectionnés pour la réponse. La vérification ne découvre pas d’autres noms. Valeurs acceptées: `true`, `false`, `1`, `0`, `yes` et `no`. Valeur par défaut: `false`. |
| include_wildcards optionnel | boolean token | Renvoie les indices de certificats wildcard dans un tableau `wildcards` séparé. Les wildcards ne sont pas mélangés aux résultats de noms d’hôte concrets. Valeurs acceptées: `true`, `false`, `1`, `0`, `yes` et `no`. Valeur par défaut: `false`. |
| limit optionnel | integer | Nombre maximal d’entrées de noms d’hôte concrets à renvoyer. Saisissez un entier compris entre 1 et 2000. Valeur par défaut: 500. |
| cursor optionnel | string | Le `next_cursor` de la page précédente. Voir la [pagination](https://domscan.net/docs/response-format#pagination). |

#### Cas d'utilisation

- Mappage de la surface d'attaque et audits de sécurité

- Examiner les noms d’hôte potentiellement oubliés ou issus du shadow IT

- Diligence raisonnable technique pré-acquisition

- Analyse concurrentielle de l'infrastructure

- Reconnaissance de programme de bounty sur les bugs

#### Champs de réponse

| Champ | Description |
| --- | --- |
| `subdomains[].name` | Nom d’hôte renvoyé. Le domaine apex peut apparaître si une source l’inclut. |
| `subdomains[].source` | Examinez les indices publics sur les noms d’hôte avec des sources clairement indiquées |
| `subdomains[].first_seen` | Les entrées issues de CT indiquent la première valeur not-before du certificat trouvée. Les sources passives de secours peuvent renvoyer null. |
| `subdomains[].verified` | true uniquement lorsque verify est activé et que la requête DNS du nom d’hôte renvoyé trouve un enregistrement A ou CNAME. Sinon, false. |
| `subdomains[].dns_records` | Enregistrements A ou CNAME issus de la vérification facultative du nom d’hôte renvoyé, ou null. Ce champ n’ajoute aucun nom au résultat. |
| `summary.total_found` | Nombre total d’entrées de noms d’hôte concrets trouvées avant la limite de la réponse, domaine apex compris si une source l’inclut. |
| `summary.verified_count` | Nombre de noms d’hôte renvoyés pour lesquels la vérification DNS facultative a trouvé un enregistrement A ou CNAME. |

#### Codes de statut HTTP

| Codes de statut HTTP | Description |
| --- | --- |
| `200` OK | Requête réussie |
| `202` Accepté | Absence de cache de sous-domaines en mode cache uniquement acceptée pour une actualisation en arrière-plan. Aucun crédit n’est facturé; réessayez après le délai Retry-After. |
| `400` Requête incorrecte | Paramètres invalides |
| `402` Paiement requis | Crédits insuffisants pour exécuter cette requête. |
| `503` Service indisponible | Le service amont est indisponible ou limite temporairement les requêtes. |
| `504` Délai d’attente de la passerelle dépassé | La requête amont a expiré. |

#### Exemple de requête

```bash
curl -H "X-API-Key: your-api-key" "https://domscan.net/v1/subdomains?domain=example.com&sources=ct&include_wildcards=yes&limit=100"

curl -H "X-API-Key: your-api-key" "https://domscan.net/v1/subdomains?domain=example.com&sources=ct&verify=yes&limit=50"

curl -H "X-API-Key: your-api-key" "https://domscan.net/v1/subdomains?domain=example.com&prefer_cache=1"
```

```python
import requests

domscan = requests.Session()
domscan.headers.update({"X-API-Key": "your-api-key"})

response = domscan.get(
    "https://domscan.net/v1/subdomains",
    params={
        "domain": "example.com",
        "sources": "ct",
        "verify": "yes",
        "include_wildcards": "yes",
        "limit": 100
    }
)
data = response.json()

print(f"Returned {data['summary']['returned']} hostname entries")
print(f"Verified: {data['summary']['verified_count']}")

live_subs = [s for s in data['subdomains'] if s['verified']]
for sub in live_subs[:10]:
    print(f"  {sub['name']}")
```

```javascript
const domscanFetch = (url, options = {}) =>
  fetch(url, {
    ...options,
    headers: { ...options.headers, "X-API-Key": "your-api-key" },
  });

const response = await domscanFetch(
  'https://domscan.net/v1/subdomains?' + new URLSearchParams({
    domain: 'example.com',
    sources: 'ct',
    verify: 'yes',
    include_wildcards: 'yes',
    limit: '100'
  })
);
const data = await response.json();

console.log(`Returned ${data.summary.returned} hostname entries`);
console.log(`Verified: ${data.summary.verified_count}`);

data.subdomains
  .filter(s => s.verified)
  .forEach(s => console.log(`  ${s.name}`));
```

#### Exemple de réponse

```json
{
  "domain": "example.com",
  "subdomains": [
    {
      "name": "api.example.com",
      "source": "crtsh",
      "first_seen": "2025-01-15T00:00:00Z",
      "verified": true,
      "dns_records": {
        "A": ["192.0.2.10"],
        "CNAME": null
      }
    }
  ],
  "wildcards": [
    {
      "pattern": "*.example.com",
      "source": "crtsh",
      "first_seen": "2024-11-20T00:00:00Z"
    }
  ],
  "summary": {
    "total_found": 1,
    "returned": 1,
    "verified_count": 1,
    "unverified_count": 0,
    "sources_used": ["crtsh"],
    "apex_included": false,
    "wildcard_suppressed_count": 1,
    "wildcard_returned_count": 1
  },
  "intelligence_summary": {
    "data_sources": ["crtsh"],
    "source_count": 1,
    "cache_status": "live",
    "returned_count": 1,
    "total_found": 1,
    "truncated": false,
    "limit": 100,
    "verification_requested": true,
    "include_wildcards": true,
    "verified_count": 1,
    "verified_ratio": 1,
    "live_dns_record_count": 1,
    "apex_included": false,
    "wildcard_suppressed_count": 1,
    "wildcard_returned_count": 1,
    "first_seen_oldest": "2025-01-15T00:00:00Z",
    "first_seen_newest": "2025-01-15T00:00:00Z",
    "warning_count": 0
  },
  "meta": {
    "query_time_ms": 184,
    "cached": false
  }
}
```

#### 202 Accepté

```json
{
  "status": "pending",
  "code": "CACHE_MISS_REFRESH_QUEUED",
  "message": "Try again in a moment",
  "domain": "example.com",
  "retry_after": 30,
  "credits_charged": 0,
  "billing_status": "not_charged",
  "request_id": "m8abc12-x9y8"
}
```

POST /v1/subdomains/bulk Crédits: 4-5/item

#### Paramètres de requête

| Paramètre | Type | requis |
| --- | --- | --- |
| dry_run | string Valeurs autorisées `true` | optionnel |

#### Paramètres du corps

| Paramètre | Type | requis |
| --- | --- | --- |
| domains | string[] | requis |
| verify | boolean Défaut `false` | optionnel |
| include_wildcards | boolean Défaut `false` | optionnel |
| limit | integer Défaut `500` | optionnel |

#### Champs de réponse

| Champ | Type |
| --- | --- |
| `results[]` | unknown[] |
| `meta` | object |
| `meta.total` | integer |
| `meta.succeeded` | integer |
| `meta.failed` | integer |
| `meta.max_items` | integer |
| `meta.credits_per_item` | integer |
| `meta.duration_ms` | integer |

#### Exemple de requête

```bash
curl -X POST "https://domscan.net/v1/subdomains/bulk" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $DOMSCAN_API_KEY" \
  -d '{
  "domains": [
    "example.com",
    "cloudflare.com"
  ],
  "verify": false,
  "limit": 500
}'
```

```javascript
const response = await fetch("https://domscan.net/v1/subdomains/bulk", {
  method: "POST",
  headers: { "X-API-Key": process.env.DOMSCAN_API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    "domains": [
      "example.com",
      "cloudflare.com"
    ],
    "verify": false,
    "limit": 500
  }),
});
const data = await response.json();
console.log(data);
```

```python
import os
import requests

response = requests.post(
    "https://domscan.net/v1/subdomains/bulk",
    headers={"X-API-Key": os.environ["DOMSCAN_API_KEY"]},
    json={
        "domains": [
            "example.com",
            "cloudflare.com",
        ],
        "verify": False,
        "limit": 500,
    },
)
print(response.json())
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	body := strings.NewReader(`{
	  "domains": [
	    "example.com",
	    "cloudflare.com"
	  ],
	  "verify": false,
	  "limit": 500
	}`)
	req, err := http.NewRequest(http.MethodPost, "https://domscan.net/v1/subdomains/bulk", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("X-API-Key", os.Getenv("DOMSCAN_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	data, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(resp.Status, string(data))
}
```

```ruby
require "json"
require "net/http"

uri = URI("https://domscan.net/v1/subdomains/bulk")
request = Net::HTTP::Post.new(uri)
request["X-API-Key"] = ENV.fetch("DOMSCAN_API_KEY")
request["Content-Type"] = "application/json"
request.body = JSON.generate({
  "domains" => [
    "example.com",
    "cloudflare.com"
  ],
  "verify" => false,
  "limit" => 500
})

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end
puts JSON.pretty_generate(JSON.parse(response.body))
```

#### Exemple de réponse

```json
{
  "results": [
    {
      "input": "example",
      "data": {}
    }
  ],
  "meta": {
    "total": 1,
    "succeeded": 1,
    "failed": 1,
    "max_items": 10,
    "credits_per_item": 1,
    "duration_ms": 1
  }
}
```

#### Codes de statut HTTP

- `200` OK
- `400` Requête incorrecte
- `401` Non autorisé
- `402` Paiement requis
- `409` HTTP 409
- `422` HTTP 422
- `429` Trop de requêtes
