API Sitemap Crawler#

Beta privata. Discover è già chiamabile oggi con la tua normale chiave API, su qualsiasi piano compreso Founding, e scala dalla tua quota mensile di ops come ogni altra chiamata. Non è annunciato né disponibile in generale: le forme di richiesta e risposta possono cambiare senza preavviso e non c'è alcun impegno di stabilità o di supporto, quindi non costruirci ancora sopra nulla di critico. La roadmap è su In arrivo, e ogni rilascio viene annunciato nel changelog.

POST /v2/discover è un'API di sitemap crawling che elenca gli URL di un sito in modo economico: una scansione HTTP-first più il parsing della sitemap, con un fallback opzionale di rendering JavaScript per le single-page app. Non c'è alcuno screenshot, alcun PDF né alcun artefatto salvato. Restituisce un elenco piatto e deduplicato di URL con un conteggio di provenienza per ciascuno, in modo sincrono in un'unica chiamata. Sarà la primitiva leggera per "mappare il sito": puntala a un dominio, ottieni le pagine che vale la pena elaborare, poi passa quell'elenco all'endpoint perceive oppure a un job di ingest in modalità crawl.

Ecco la chiamata minima utile. Invia un URL, ricevi la sua mappa:

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 risposta è un semplice elenco di URL con contatori di provenienza. Non ci sono URL firmati, né ID operazione, né 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#

Metodo Percorso Scopo
POST /v2/discover Mappa gli URL di un sito solo via HTTP e restituisce un elenco piatto con i conteggi per fonte.

/v2/discover espone un solo percorso. È stateless: non c'è una riga di operazione da recuperare né un job da interrogare, quindi non esiste un endpoint GET di supporto come avviene per perceive.

Content-Type: application/json sulla POST.


Autenticazione#

Autenticati con una chiave privata nell'header X-API-Key per le chiamate server-to-server. È il percorso usato negli esempi qui sotto.

X-API-Key: sk_your_private_key

Funzionano anche le chiavi pubbliche con un token bearer JWT, usando lo stesso flusso di ogni altro endpoint: genera un token con la tua chiave pk_, poi invialo come Authorization: Bearer <token>. Il flusso completo, incluso il domain locking e il refresh del token, si trova nella guida all'autenticazione.

Ogni chiave API porta con sé un'allowlist di endpoint consentiti. Se /v2/discover non è nell'elenco della chiave, la richiesta viene rifiutata con 403 e un messaggio che indica il percorso bloccato.


Come funziona discover#

Una richiesta viene eseguita interamente via HTTP. Il singleton Chrome headless che alimenta perceive non viene mai toccato. Il percorso di crawl usa la strategia di crawler HTTP di Crawl4AI (una GET httpx più un parsing dei link con lxml per pagina), e il percorso sitemap riutilizza gli stessi helper puramente HTTP per sitemap e feed usati dal resto della piattaforma.

  1. Verifica del seed. L'URL che invii viene controllato per SSRF prima di qualsiasi fetch: schema, credenziali incorporate, hostname bloccati e IP risolto vengono tutti validati. Un URL che si risolve in un indirizzo privato, loopback, link-local o di metadata cloud viene rifiutato con 400. Il seed è sempre incluso come prima voce nella propria mappa.
  2. Raccolta dalle sitemap. In modalità sitemap o hybrid, discover legge robots.txt e recupera gli URL Sitemap: che vi sono dichiarati, sonda sitemap.xml (ricorrendo nei figli <sitemapindex>), ed estrae le pagine dei feed RSS/Atom. Esegue questi controlli sia sull'host che hai inviato sia sul dominio registrabile (apex) del sito, così una sitemap pubblicata solo sull'apex viene comunque trovata a partire da un seed su un sottodominio o su un percorso profondo. Una sitemap mancante o non funzionante diventa un warning, non un errore.
  3. Crawl via HTTP. In modalità crawl o hybrid, discover esegue una scansione breadth-first a partire dal seed fino a max_depth, raccogliendo i link <a href> dall'HTML grezzo di ogni pagina recuperata. Ogni link seguito viene sottoposto a screening SSRF prima di essere recuperato.
  4. Normalizzazione e filtro. L'elenco grezzo combinato viene canonicalizzato (frammenti e parametri di tracking rimossi, porte predefinite eliminate, chiavi di query ordinate), poi passa attraverso il controllo dello stesso dominio, i tuoi pattern regex di inclusione ed esclusione, il filtro robots.txt, la deduplicazione e infine il tetto di max_urls.

Sul percorso solo HTTP, una single-page app renderizzata lato client restituisce solo il proprio HTML shell in modalità crawl, tipicamente il seed più zero o un URL. Il fallback opzionale render_js (vedi Rendering JavaScript) colma questa lacuna: nella sua impostazione predefinita "auto", discover renderizza la pagina una volta nel browser e raccoglie i link che essa inietta a runtime ogni volta che la scansione HTTP restituisce solo uno shell. La modalità sitemap resta un percorso veloce e senza browser per le SPA attente alla SEO, che di norma pubblicano una sitemap.


Parametri della richiesta#

Principali#

Parametro Tipo Predefinito Descrizione
url string nessuno Il sito da mappare. Deve iniziare con http:// o https://. Massimo 2,048 caratteri. Obbligatorio.
mode string "hybrid" sitemap, crawl o hybrid. Vedi Modalità.
max_urls integer 100 Numero massimo di URL restituiti. 1–1,000. L'elenco viene limitato qui e truncated segnala se ne esistevano altri.
max_depth integer 2 Profondità di scansione dal seed, in modalità crawl/hybrid. 1–5.
same_domain_only boolean true Mantiene solo gli URL sull'host del seed. Quando è false, vengono mantenuti anche i link fuori host scoperti durante la scansione.
render_js string "auto" Scoperta renderizzata nel browser per siti JavaScript/SPA (solo crawl/hybrid). auto renderizza solo quando la scansione HTTP restituisce uno shell; always la forza; never resta solo HTTP. Vedi Rendering JavaScript.

Filtri#

Parametro Tipo Predefinito Descrizione
include_patterns string[] [] Allowlist di regex Python (semantica re.search, non glob). Un URL deve corrispondere ad almeno una per essere mantenuto. Vuoto significa consenti tutto. Massimo 50 pattern.
exclude_patterns string[] [] Denylist di regex Python. Un URL che corrisponde a qualsiasi pattern viene scartato. Applicata dopo include_patterns. Massimo 50 pattern.
respect_robots boolean false Quando è true, gli URL non consentiti dal robots.txt del sito vengono rimossi dall'elenco restituito.

I pattern sono vere espressioni regolari Python, compilate al momento della validazione. Un pattern malformato produce un 422 al bordo, non un 500 a metà scansione. Poiché la semantica è re.search, una semplice sottostringa come "/blog/" corrisponde ovunque nell'URL, quindi ancorala con ^/$ se ti serve una corrispondenza posizionale.

Da segnalare subito. respect_robots viene applicato al momento del filtro in output, non al momento del fetch. Crawl4AI 0.8.9 non ha un gate robots nativo, quindi in modalità crawl o hybrid una pagina non consentita può comunque essere recuperata via HTTP e poi scartata prima di raggiungere la risposta. A differenza di perceive, dove respect_robots=true rifiuta un URL non consentito con 403, discover non restituisce mai 403 per una regola robots. Scarta silenziosamente l'URL e non riporta nulla.

Modalità#

mode Cosa fa
sitemap Voci sitemap da robots.txt, sitemap.xml sondato (con ricorsione sull'indice) e pagine dei feed RSS/Atom. Istantaneo, nessuna scansione.
crawl Scansione breadth-first solo HTTP a partire dal seed, che raccoglie i link <a href> dal markup grezzo.
hybrid (predefinita) L'unione deduplicata di sitemap e crawl.

La modalità crawl recupera fino al tuo max_urls completo (fino a 1,000), così un sito grande viene enumerato in un solo passaggio. La modalità crawl è solo HTTP (nessun browser), quindi resta veloce. Gli operatori possono abbassare il tetto con la variabile d'ambiente DISCOVER_CRAWL_MAX_PAGES se una scansione molto grande dovesse mai richiedere un limite. pages_crawled nella risposta ti dice esattamente quante GET sono state eseguite.

Il fetch delle sitemap gestisce le sitemap compresse con gzip (sitemap.xml.gz e qualsiasi sitemap servita come application/gzip), e invia header da browser realistici, così i siti dietro un WAF hanno molte più probabilità di restituire la loro sitemap invece di un 403/503.

Rendering JavaScript#

Le modalità crawl e hybrid leggono l'HTML grezzo che un server restituisce, quindi una single-page app renderizzata lato client che costruisce i propri link nel browser è invisibile per loro. render_js attiva un fallback browser limitato che colma questa lacuna:

render_js Cosa fa
auto (predefinito) Esegue prima la scansione HTTP; renderizza nel browser solo quando questa restituisce uno shell nudo (un URL o nessuno), poi raccoglie i link iniettati lato client.
always Esegue sempre la scansione renderizzata nel browser.
never Resta rigorosamente solo HTTP, il comportamento preesistente.

Il fallback usa lo stesso Chrome headless condiviso di perceive ed è limitato a poche pagine così che la chiamata resti entro il timeout della richiesta. I link che trova vengono conteggiati sotto la chiave crawl_js in sources. Si applica solo alle modalità crawl e hybrid, perché la modalità sitemap è già senza browser e non ne è influenzata.


Risposta#

POST /v2/discover restituisce direttamente questo oggetto, senza alcun job asincrono né una seconda chiamata.

Campo Tipo Descrizione
url string L'URL seed che hai inviato.
mode string La modalità eseguita: sitemap, crawl o hybrid.
total integer Numero di URL in urls (dopo dedup, filtro e limite).
urls string[] L'elenco di URL deduplicato, normalizzato e limitato. Il seed è sempre il primo candidato.
pages_crawled integer GET HTTP emesse dalla scansione. 0 in modalità sitemap pura.
truncated boolean true quando esistevano più URL unici di quanti ne permettesse max_urls.
robots_respected boolean Rispecchia il valore di respect_robots che hai inviato.
sources object Conteggio grezzo di URL per fonte prima di dedup/filtro, ad es. {"sitemap": 42, "crawl": 30}. Le chiavi includono sitemap, crawl, sitemap_apex (sitemap trovate sul dominio apex) e crawl_js (link dal fallback di rendering JavaScript). I conteggi si sovrappongono e sommano oltre total.
warnings string[] Note non fatali: una sitemap mancante, una scansione fallita, un robots.txt irraggiungibile.

I conteggi di sources sono grezzi: rappresentano il numero di URL prodotti da ciascun percorso prima che venissero eseguiti la normalizzazione, il controllo dello stesso dominio, i tuoi filtri e la deduplicazione. Di norma sommano più di total, perché la modalità hybrid trova le stesse pagine sia dalla sitemap sia dalla scansione. Usali per capire quale percorso sta portando la mappa, non come conteggio post-filtro.


Esempi di codice#

curl: mappa hybrid predefinita#

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: solo sitemap, pagine del blog, limite a 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));

Uno schema comune è scoprire prima e poi renderizzare: prendi data.urls e passalo all'endpoint perceive, con chiamate singole per una manciata di pagine oppure il suo percorso batch per l'intero elenco.


Risposte di errore#

Stato Condizione
400 Bad Request L'URL non è http(s), contiene credenziali incorporate, non ha hostname, oppure si risolve in un indirizzo privato, loopback, link-local o di metadata cloud (protezione SSRF).
401 Unauthorized Chiave API / token JWT mancante o non valido.
402 Payment Required Discover non è abilitato sul tuo piano attuale, oppure la tua quota mensile di ops è esaurita. Ogni chiamata a /v2/discover addebita una op.
403 Forbidden /v2/discover non è tra gli endpoint consentiti della chiave API.
422 Unprocessable Entity Validazione della richiesta fallita: enum mode non valido, max_urls fuori da 1–1,000, max_depth fuori da 1–5, oltre 50 pattern include/exclude, una regex malformata, oppure un url oltre 2,048 caratteri.
500 Internal Server Error La scoperta degli URL è fallita inaspettatamente. Il client riceve un messaggio generico; il dettaglio completo va solo nei log del server.

Nota che un fetch della sitemap fallito o un errore di scansione non producono uno stato di errore. Questi degradano a voci nell'array warnings, e la richiesta restituisce comunque 200 con tutto ciò che è stato trovato. Il riferimento completo dei codici di stato è nella guida ai codici di errore.


Limiti#

Limite Valore
Lunghezza URL 2,048 caratteri
max_urls 1–1,000 (predefinito 100)
max_depth 1–5 (predefinito 2)
include_patterns Massimo 50 pattern
exclude_patterns Massimo 50 pattern
Pagine recuperate in modalità crawl fino a max_urls (max 1,000; abbassabile con DISCOVER_CRAWL_MAX_PAGES)
Timeout richiesta 300 secondi
Ops per chiamata 1, addebitata sulla quota mensile unificata

Domande frequenti#

Come elenco tutti gli URL di un sito web con un'API?#

Invia POST /v2/discover con l'URL del sito. La modalità predefinita hybrid combina il parsing della sitemap (voci robots.txt, sitemap.xml con ricorsione sull'indice, feed RSS/Atom) con una scansione HTTP breadth-first, e restituisce fino a max_urls (1–1,000, predefinito 100) URL deduplicati in un'unica risposta sincrona.

L'endpoint discover usa un browser headless o renderizza JavaScript?#

Per impostazione predefinita viene eseguito via HTTP e renderizza solo quando è necessario. L'opzione render_js controlla questo comportamento: nella modalità predefinita "auto", discover resta solo HTTP e renderizza una pagina nel browser solo quando la scansione HTTP restituisce uno shell JavaScript nudo, raccogliendo i link iniettati lato client; "always" forza la scansione nel browser e "never" la mantiene rigorosamente solo HTTP. La modalità sitemap resta un'opzione veloce e senza browser per le SPA attente alla SEO.

Quante pagine recupera effettivamente la modalità crawl?#

La modalità crawl recupera fino al tuo max_urls completo (fino a 1,000). Resta solo HTTP, quindi rimane veloce; gli operatori possono abbassare il tetto con la variabile d'ambiente DISCOVER_CRAWL_MAX_PAGES. Ogni pagina recuperata contribuisce inoltre con molti link. Il campo pages_crawled della risposta riporta esattamente quante GET HTTP sono state eseguite.

Posso filtrare quali URL vengono restituiti?#

Sì. include_patterns e exclude_patterns accettano fino a 50 regex Python ciascuno (semantica re.search, non glob), e respect_robots: true rimuove dall'elenco restituito gli URL non consentiti dal robots.txt del sito.