API de crawl de sitemap#

Bêta privée. Discover est appelable dès aujourd'hui avec votre clé d'API habituelle, sur tous les forfaits y compris Founding, et décompte votre quota mensuel d'ops comme n'importe quel autre appel. Ce n'est ni annoncé ni disponible de façon générale : les formes de requête et de réponse peuvent changer sans préavis, et il n'y a aucun engagement de stabilité ni de support, donc ne construisez rien de critique dessus pour l'instant. La feuille de route est sur Bientôt disponible, et chaque publication est annoncée dans le changelog.

POST /v2/discover est une API de crawl de sitemap qui liste les URLs d'un site à moindre coût : un crawl en priorité HTTP combiné à un parsing de sitemap, avec un repli de rendu JavaScript optionnel pour les applications monopage (SPA). Il n'y a ni capture d'écran, ni PDF, ni artefact stocké. Elle renvoie une liste plate et dédupliquée d'URLs ainsi qu'un décompte de la provenance de chacune, de façon synchrone en un seul appel. Ce sera la primitive légère « cartographier le site » : pointez-la vers un domaine, récupérez les pages qui méritent d'être traitées, puis injectez cette liste dans l'endpoint perceive ou dans un job d'ingestion en mode crawl.

Voici l'appel minimal utile. Envoyez une URL, récupérez sa carte :

curl -X POST https://api.enconvert.com/v2/discover \
  -H "X-API-Key: sk_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com"
  }'

La réponse est une simple liste d'URLs avec des compteurs de provenance. Il n'y a pas d'URLs signées, pas d'ID d'opération et pas de polling :

{
    "url": "https://example.com",
    "mode": "hybrid",
    "total": 47,
    "urls": [
        "https://example.com/",
        "https://example.com/pricing",
        "https://example.com/docs",
        "https://example.com/blog/launch"
    ],
    "pages_crawled": 12,
    "truncated": false,
    "robots_respected": false,
    "sources": {"sitemap": 42, "crawl": 30},
    "warnings": []
}

Endpoints#

Méthode Chemin Objectif
POST /v2/discover Cartographie les URLs d'un site en HTTP uniquement et renvoie une liste plate avec des compteurs par source.

/v2/discover expose un seul chemin. Il est sans état : il n'y a aucune ligne d'opération à récupérer ni aucun job à interroger, donc il n'existe pas d'endpoint GET compagnon comme c'est le cas pour perceive.

Content-Type : application/json sur le POST.


Authentification#

Authentifiez-vous avec une clé privée dans l'en-tête X-API-Key pour les appels serveur à serveur. C'est la voie utilisée par les exemples ci-dessous.

X-API-Key: sk_your_private_key

Les clés publiques avec un jeton bearer JWT fonctionnent également, selon le même flux que tous les autres endpoints : générez un jeton avec votre clé pk_, puis envoyez-le en tant que Authorization: Bearer <token>. Le flux complet, y compris le verrouillage de domaine et le renouvellement du jeton, se trouve dans le guide d'authentification.

Chaque clé API dispose d'une liste d'endpoints autorisés. Si /v2/discover ne figure pas dans la liste de la clé, la requête est rejetée avec 403 et un message précisant le chemin bloqué.


Fonctionnement de discover#

Une requête s'exécute entièrement en HTTP. Le Chrome headless singleton qui alimente perceive n'est jamais sollicité. Le chemin de crawl utilise la stratégie de crawler HTTP de Crawl4AI (un GET httpx suivi d'un parsing de liens lxml par page), et le chemin sitemap réutilise les mêmes helpers sitemap et feed purement HTTP que le reste de la plateforme.

  1. Filtrer l'URL de départ. L'URL que vous envoyez est vérifiée contre le SSRF avant toute requête : le schéma, les identifiants intégrés, les noms d'hôte bloqués et l'IP résolue sont tous validés. Une URL qui résout vers une adresse privée, loopback, link-local ou de métadonnées cloud est rejetée avec 400. L'URL de départ est toujours incluse comme première entrée de sa propre carte.
  2. Collecter depuis les sitemaps. En mode sitemap ou hybrid, discover lit robots.txt et récupère les URLs Sitemap: qu'il déclare, sonde sitemap.xml (en récursant dans les enfants <sitemapindex>), et récupère les pages de flux RSS/Atom. Elle exécute ces sondes à la fois contre l'hôte que vous avez envoyé et contre le domaine enregistrable (apex) du site, de sorte qu'un sitemap publié uniquement sur l'apex est quand même trouvé depuis un sous-domaine ou une URL de départ à chemin profond. Un sitemap manquant ou cassé devient un avertissement, pas une erreur.
  3. Crawler en HTTP. En mode crawl ou hybrid, discover exécute un crawl en largeur depuis l'URL de départ jusqu'à max_depth, en récupérant les liens <a href> de chaque page brute récupérée. Chaque lien suivi est filtré contre le SSRF avant d'être récupéré.
  4. Normaliser et filtrer. La liste brute combinée est canonicalisée (fragments et paramètres de tracking supprimés, ports par défaut retirés, clés de requête triées), puis passée par la vérification du même domaine, vos motifs regex d'inclusion et d'exclusion, le filtre robots.txt, la déduplication, et enfin le plafond max_urls.

Sur le chemin HTTP uniquement, une application monopage (SPA) rendue côté client ne renvoie que sa coquille HTML en mode crawl, typiquement l'URL de départ plus zéro ou une URL. Le repli optionnel render_js (voir Rendu JavaScript) comble cette lacune : dans son réglage "auto" par défaut, discover effectue le rendu de la page une fois dans le navigateur et récolte les liens qu'elle injecte à l'exécution chaque fois que le crawl HTTP ne renvoie qu'une coquille. Le mode sitemap reste une voie rapide et sans navigateur pour les SPA soucieuses du SEO, qui publient généralement un sitemap.


Paramètres de la requête#

Paramètres de base#

Paramètre Type Défaut Description
url string aucun Le site à cartographier. Doit commencer par http:// ou https://. Max 2,048 caractères. Obligatoire.
mode string "hybrid" sitemap, crawl ou hybrid. Voir Modes.
max_urls integer 100 Nombre maximum d'URLs renvoyées. De 1 à 1,000. La liste est plafonnée ici et truncated l'indique si davantage existait.
max_depth integer 2 Profondeur de crawl depuis l'URL de départ, en mode crawl/hybrid. De 1 à 5.
same_domain_only boolean true Ne conserve que les URLs sur l'hôte de l'URL de départ. Quand false, les liens hors hôte découverts pendant le crawl sont aussi conservés.
render_js string "auto" Découverte par rendu navigateur pour les sites JavaScript/SPA (crawl/hybrid uniquement). auto n'effectue le rendu que lorsque le crawl HTTP renvoie une coquille ; always le force ; never reste en HTTP uniquement. Voir Rendu JavaScript.

Filtrage#

Paramètre Type Défaut Description
include_patterns string[] [] Liste d'autorisation de regex Python (sémantique re.search, pas de glob). Une URL doit correspondre à au moins un motif pour être conservée. Vide signifie tout autoriser. Max 50 motifs.
exclude_patterns string[] [] Liste de blocage de regex Python. Une URL correspondant à un motif quelconque est écartée. Appliqué après include_patterns. Max 50 motifs.
respect_robots boolean false Quand true, les URLs interdites par le robots.txt du site sont retirées de la liste renvoyée.

Les motifs sont de véritables expressions régulières Python, compilées au moment de la validation. Un motif malformé produit un 422 en amont, pas un 500 en plein crawl. Comme la sémantique est celle de re.search, une simple sous-chaîne comme "/blog/" correspond n'importe où dans l'URL, donc ancrez avec ^/$ si vous avez besoin d'une correspondance positionnelle.

À signaler d'emblée. respect_robots est appliqué au moment du filtrage de sortie, pas au moment de la récupération. Crawl4AI 0.8.9 n'a pas de blocage robots natif, donc en mode crawl ou hybrid une page interdite peut quand même être récupérée en HTTP puis écartée avant d'atteindre la réponse. Contrairement à perceive, où respect_robots=true rejette une URL interdite avec 403, discover ne renvoie jamais 403 pour une règle robots. Elle retire l'URL en silence et ne le signale nulle part.

Modes#

mode Ce que ça fait
sitemap Entrées sitemap de robots.txt, sitemap.xml sondé (avec récursion d'index), et pages de flux RSS/Atom. Instantané, sans crawl.
crawl Crawl HTTP pur en largeur depuis l'URL de départ, récupérant les liens <a href> du balisage brut.
hybrid (par défaut) L'union dédupliquée de sitemap et crawl.

Le mode crawl récupère jusqu'à votre max_urls complet (jusqu'à 1,000), de sorte qu'un grand site est énuméré en une seule passe. Le mode crawl est purement HTTP (pas de navigateur), donc cela reste rapide. Les opérateurs peuvent abaisser ce plafond avec la variable d'environnement DISCOVER_CRAWL_MAX_PAGES si un très grand crawl doit un jour être borné. pages_crawled dans la réponse vous indique exactement combien de GET ont été exécutés.

La récupération de sitemap gère les sitemaps compressés en gzip (sitemap.xml.gz et tout sitemap servi en application/gzip), et envoie des en-têtes de navigateur réalistes, de sorte que les sites derrière un WAF sont bien plus susceptibles de renvoyer leur sitemap plutôt qu'un 403/503.

Rendu JavaScript#

Les modes crawl et hybrid lisent le HTML brut renvoyé par un serveur, de sorte qu'une application monopage (SPA) rendue côté client, qui construit ses liens dans le navigateur, leur est invisible. render_js active un repli navigateur borné qui comble cette lacune :

render_js Ce que ça fait
auto (par défaut) Exécute d'abord le crawl HTTP ; n'effectue le rendu dans le navigateur que lorsqu'il ne renvoie qu'une coquille nue (une URL ou aucune), puis récolte les liens injectés côté client.
always Exécute toujours le crawl par rendu navigateur.
never Reste strictement en HTTP uniquement, le comportement préexistant.

Le repli utilise le même Chrome headless partagé que perceive et est plafonné à quelques pages afin que l'appel reste dans le timeout de la requête. Les liens qu'il trouve sont comptabilisés sous la clé crawl_js dans sources. Il s'applique aux modes crawl et hybrid uniquement, car le mode sitemap est déjà sans navigateur et n'est pas affecté.


Réponse#

POST /v2/discover renvoie directement cet objet, sans job asynchrone ni second appel.

Champ Type Description
url string L'URL de départ que vous avez envoyée.
mode string Le mode exécuté : sitemap, crawl ou hybrid.
total integer Nombre d'URLs dans urls (après déduplication, filtrage et plafonnement).
urls string[] La liste d'URLs dédupliquée, normalisée et plafonnée. L'URL de départ est toujours le premier candidat.
pages_crawled integer GET HTTP émis par le crawl. 0 en mode sitemap pur.
truncated boolean true quand il existait plus d'URLs uniques que max_urls n'en autorisait.
robots_respected boolean Reprend la valeur de respect_robots que vous avez envoyée.
sources object Décompte brut d'URLs par source avant déduplication/filtrage, ex. {"sitemap": 42, "crawl": 30}. Les clés incluent sitemap, crawl, sitemap_apex (sitemaps trouvés sur le domaine apex) et crawl_js (liens issus du repli de rendu JavaScript). Les décomptes se chevauchent et leur somme dépasse total.
warnings string[] Notes non bloquantes : un sitemap manquant, un crawl en échec, un robots.txt inaccessible.

Les décomptes de sources sont bruts : ce sont les nombres d'URLs produits par chaque chemin avant la normalisation, la vérification du même domaine, vos filtres et la déduplication. Ils dépassent régulièrement total, parce que le mode hybrid retrouve les mêmes pages à la fois via le sitemap et le crawl. Utilisez-les pour voir quel chemin porte la carte, pas comme un décompte post-filtrage.


Exemples de code#

curl : carte hybride par défaut#

curl -X POST https://api.enconvert.com/v2/discover \
  -H "X-API-Key: sk_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com"
  }'

curl : sitemap uniquement, pages de blog, plafonné à 500#

curl -X POST https://api.enconvert.com/v2/discover \
  -H "X-API-Key: sk_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "mode": "sitemap",
    "max_urls": 500,
    "include_patterns": ["/blog/"],
    "exclude_patterns": ["/tag/", "/author/"],
    "respect_robots": true
  }'

Python#

import requests

response = requests.post(
    "https://api.enconvert.com/v2/discover",
    headers={"X-API-Key": "sk_your_private_key"},
    json={
        "url": "https://example.com",
        "mode": "hybrid",
        "max_urls": 200,
        "include_patterns": [r"/docs/"],
    },
)
response.raise_for_status()
data = response.json()

print(f"found {data['total']} URLs from {data['sources']}")
for page_url in data["urls"]:
    print(page_url)

Node.js#

const res = await fetch("https://api.enconvert.com/v2/discover", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-API-Key": "sk_your_private_key"
    },
    body: JSON.stringify({
        url: "https://example.com",
        mode: "hybrid",
        max_urls: 200,
        include_patterns: ["/docs/"]
    })
});

const data = await res.json();

console.log(`found ${data.total} URLs from`, data.sources);
data.urls.forEach((pageUrl) => console.log(pageUrl));

Un pattern courant consiste à découvrir d'abord, puis à rendre : prenez data.urls et transmettez-les à l'endpoint perceive, avec des appels individuels pour une poignée de pages ou son chemin batch pour la liste entière.


Réponses d'erreur#

Statut Condition
400 Bad Request L'URL n'est pas en http(s), contient des identifiants intégrés, n'a pas de nom d'hôte, ou résout vers une adresse privée, loopback, link-local ou de métadonnées cloud (protection SSRF).
401 Unauthorized Clé API / jeton JWT manquant ou invalide.
402 Payment Required Discover n'est pas activé sur votre plan actuel, ou votre quota mensuel d'ops est épuisé. Chaque appel /v2/discover facture une op.
403 Forbidden /v2/discover ne figure pas dans les endpoints autorisés de la clé API.
422 Unprocessable Entity Échec de validation de la requête : énumération mode invalide, max_urls en dehors de la plage 1 à 1,000, max_depth en dehors de la plage 1 à 5, plus de 50 motifs include/exclude, une regex malformée, ou une url de plus de 2,048 caractères.
500 Internal Server Error La découverte d'URLs a échoué de façon inattendue. Le client reçoit un message générique ; le détail complet ne va que dans les logs serveur.

À noter qu'un échec de récupération du sitemap ou un incident de crawl ne produit pas de statut d'erreur. Ces cas dégradent en entrées dans le tableau warnings, et la requête renvoie quand même 200 avec ce qui a été trouvé. La référence complète des codes de statut se trouve dans le guide des codes d'erreur.


Limites#

Limite Valeur
Longueur d'URL 2,048 caractères
max_urls de 1 à 1,000 (défaut 100)
max_depth de 1 à 5 (défaut 2)
include_patterns 50 motifs max
exclude_patterns 50 motifs max
Pages récupérées en mode crawl jusqu'à max_urls (max 1,000 ; à abaisser avec DISCOVER_CRAWL_MAX_PAGES)
Timeout de requête 300 secondes
Ops par appel 1, facturée sur le quota mensuel unifié

Foire aux questions#

Comment lister toutes les URLs d'un site web avec une API ?#

Envoyez POST /v2/discover avec l'URL du site. Le mode hybrid par défaut combine le parsing de sitemap (entrées robots.txt, sitemap.xml avec récursion d'index, flux RSS/Atom) avec un crawl HTTP en largeur, et renvoie jusqu'à max_urls (de 1 à 1,000, défaut 100) URLs dédupliquées en une seule réponse synchrone.

L'endpoint discover utilise-t-il un navigateur headless ou effectue-t-il du rendu JavaScript ?#

Par défaut, il s'exécute en HTTP et n'effectue le rendu que lorsqu'il le faut. L'option render_js contrôle cela : dans le mode "auto" par défaut, discover reste en HTTP uniquement et n'effectue le rendu d'une page dans le navigateur que lorsque le crawl HTTP renvoie une coquille JavaScript nue, en récoltant les liens injectés côté client ; "always" force le crawl par navigateur et "never" le maintient strictement en HTTP uniquement. Le mode sitemap reste une option rapide et sans navigateur pour les SPA soucieuses du SEO.

Combien de pages le mode crawl récupère-t-il réellement ?#

Le mode crawl récupère jusqu'à votre max_urls complet (jusqu'à 1,000). Il reste purement HTTP, donc il reste rapide ; les opérateurs peuvent abaisser ce plafond avec la variable d'environnement DISCOVER_CRAWL_MAX_PAGES. Chaque page récupérée apporte en plus de nombreux liens. Le champ pages_crawled de la réponse indique exactement combien de GET HTTP ont été exécutés.

Puis-je filtrer les URLs renvoyées ?#

Oui. include_patterns et exclude_patterns acceptent jusqu'à 50 regex Python chacun (sémantique re.search, pas de glob), et respect_robots: true retire de la liste renvoyée les URLs interdites par le robots.txt du site.