Sitemap-Crawler-API#
POST /v2/discover ist eine Sitemap-Crawler-API, die die URLs einer
Website auf die günstige Art auflistet: ein HTTP-first-Crawl plus
Sitemap-Parsing, mit einem optionalen JavaScript-Render-Fallback für
Single-Page-Apps. Es gibt keinen Screenshot, kein PDF und kein
gespeichertes Artefakt. Sie liefert eine flache,
deduplizierte Liste von URLs sowie eine Zählung, aus welcher Quelle
jede URL stammt, synchron in einem einzigen Aufruf. Sie wird das
leichtgewichtige „Website kartieren“-Primitiv sein: eine Domain angeben, die zu
verarbeitenden Seiten zurückbekommen, dann diese Liste an
den Perceive-Endpunkt oder einen Ingest-Job im
Crawl-Modus übergeben.
Hier ist der kleinste sinnvolle Aufruf. Sende eine URL, erhalte ihre Karte zurück:
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"
}'
Die Antwort ist eine einfache URL-Liste mit Herkunfts-Zählern. Es gibt keine signierten URLs, keine Operation-ID und kein 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": []
}
Endpunkte#
| Methode | Pfad | Zweck |
|---|---|---|
POST |
/v2/discover |
Ermittelt die URLs einer Website ausschließlich über HTTP und liefert eine flache Liste mit Quellenzahlen zurück. |
/v2/discover stellt einen einzigen Pfad bereit. Er ist zustandslos:
Es gibt keine Operation-Zeile zum erneuten Abrufen und keinen Job zum
Pollen, daher gibt es auch keinen begleitenden GET-Endpunkt, wie ihn
Perceive hat.
Content-Type: application/json beim POST.
Authentifizierung#
Authentifiziere dich für Server-zu-Server-Aufrufe mit einem privaten
Schlüssel im X-API-Key-Header. Diesen Weg verwenden auch die
folgenden Beispiele.
X-API-Key: sk_your_private_key
Öffentliche Schlüssel mit einem JWT-Bearer-Token funktionieren
ebenfalls, nach demselben Ablauf wie bei jedem anderen Endpunkt:
Erzeuge mit deinem pk_-Schlüssel ein Token und sende es dann als
Authorization: Bearer <token>. Der vollständige Ablauf, einschließlich
Domain-Sperre und Token-Refresh, steht in
der Authentifizierungs-Anleitung.
Jeder API-Schlüssel führt eine Allowlist erlaubter Endpunkte mit sich.
Steht /v2/discover nicht auf der Liste des Schlüssels, wird die
Anfrage mit 403 abgelehnt, samt einer Meldung, die den blockierten
Pfad nennt.
So funktioniert Discover#
Eine Anfrage läuft vollständig über HTTP ab. Das
Singleton-Headless-Chrome, das Perceive
antreibt, wird dabei nie angefasst. Der Crawl-Pfad nutzt Crawl4AIs
HTTP-Crawler-Strategie (ein httpx-GET plus ein lxml-Link-Parse pro
Seite), und der Sitemap-Pfad verwendet dieselben reinen
HTTP-Sitemap- und Feed-Helfer wie der Rest der Plattform.
- Seed prüfen. Die von dir gesendete URL wird vor jedem Abruf auf
SSRF geprüft: Schema, eingebettete Zugangsdaten, blockierte
Hostnamen und die aufgelöste IP werden allesamt validiert. Eine
URL, die zu einer privaten, Loopback-, Link-Local- oder
Cloud-Metadaten-Adresse auflöst, wird mit
400abgelehnt. Der Seed ist immer der erste Eintrag in seiner eigenen Karte. - Aus Sitemaps sammeln. Im Modus
sitemapoderhybridliest Discover dierobots.txtund ruft die dort deklariertenSitemap:-URLs ab, prüftsitemap.xml(rekursiv durch<sitemapindex>-Kindelemente) und zieht RSS/Atom-Feed-Seiten hinzu. Diese Prüfungen führt Discover sowohl gegen den von dir gesendeten Host als auch gegen die registrierbare (Apex-)Domain der Website aus, sodass eine nur auf der Apex-Domain veröffentlichte Sitemap auch von einem Subdomain- oder Deep-Path-Seed aus gefunden wird. Eine fehlende oder defekte Sitemap wird zu einer Warnung, nicht zu einem Fehler. - Über HTTP crawlen. Im Modus
crawloderhybridführt Discover ausgehend vom Seed einen Breadth-First-Crawl bismax_depthaus und sammelt dabei die<a href>-Links aus dem rohen HTML jeder abgerufenen Seite. Jeder verfolgte Link wird vor dem Abruf auf SSRF geprüft. - Normalisieren und filtern. Die zusammengeführte Rohliste wird
kanonisiert (Fragmente und Tracking-Parameter entfernt,
Standard-Ports gestrichen, Query-Keys sortiert) und durchläuft dann
die Same-Domain-Prüfung, deine Include- und Exclude-Regex-Muster,
den
robots.txt-Filter, die Deduplizierung und schließlich diemax_urls-Obergrenze.
Auf dem reinen HTTP-Pfad liefert eine clientseitig gerenderte
Single-Page-App im Modus crawl nur ihre HTML-Hülle zurück,
typischerweise den Seed plus null oder eine URL. Der optionale
render_js-Fallback (siehe JavaScript-Rendering)
schließt diese Lücke: In seiner Standardeinstellung "auto" rendert
Discover die Seite einmal im Browser und sammelt die Links, die sie
zur Laufzeit einfügt, immer dann, wenn der HTTP-Crawl nur eine Hülle
zurückliefert. Der Modus sitemap bleibt ein schneller,
browser-freier Weg für SEO-bewusste SPAs, die üblicherweise eine
Sitemap veröffentlichen.
Request-Parameter#
Kern#
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
url |
string |
-- | Die zu kartierende Website. Muss mit http:// oder https:// beginnen. Max. 2,048 Zeichen. Erforderlich. |
mode |
string |
"hybrid" |
sitemap, crawl oder hybrid. Siehe Modi. |
max_urls |
integer |
100 |
Maximale Anzahl zurückgegebener URLs. 1 bis 1,000. Die Liste wird hier begrenzt, und truncated zeigt an, ob mehr existierten. |
max_depth |
integer |
2 |
Crawl-Tiefe ab dem Seed, im Modus crawl/hybrid. 1 bis 5. |
same_domain_only |
boolean |
true |
Behält nur URLs auf dem Host des Seeds. Bei false werden auch host-fremde Links behalten, die während des Crawls entdeckt werden. |
render_js |
string |
"auto" |
Browser-gerenderte Ermittlung für JavaScript-/SPA-Seiten (nur crawl/hybrid). auto rendert nur, wenn der HTTP-Crawl eine Hülle zurückliefert; always erzwingt es; never bleibt reines HTTP. Siehe JavaScript-Rendering. |
Filterung#
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
include_patterns |
string[] |
[] |
Python-Regex-Allowlist (Semantik von re.search, kein Glob). Eine URL muss mindestens ein Muster treffen, um behalten zu werden. Leer bedeutet: alles erlauben. Max. 50 Muster. |
exclude_patterns |
string[] |
[] |
Python-Regex-Denylist. Eine URL, die auf ein Muster passt, wird verworfen. Wird nach include_patterns angewendet. Max. 50 Muster. |
respect_robots |
boolean |
false |
Bei true werden URLs, die laut der robots.txt der Website nicht erlaubt sind, aus der zurückgegebenen Liste entfernt. |
Die Muster sind echte reguläre Python-Ausdrücke, die zur
Validierungszeit kompiliert werden. Ein fehlerhaftes Muster ergibt am
Rand ein 422, nicht mitten im Crawl ein 500. Da die Semantik
re.search ist, passt ein bloßer Teilstring wie "/blog/" überall in
der URL, verankere also mit ^/$, wenn du eine positionsbezogene
Übereinstimmung brauchst.
Wichtig vorab.
respect_robotswird zum Zeitpunkt der Ausgabefilterung durchgesetzt, nicht beim Abruf. Crawl4AI 0.8.9 hat kein natives Robots-Gate, daher kann im Moduscrawloderhybrideine nicht erlaubte Seite trotzdem über HTTP abgerufen und erst danach verworfen werden, bevor sie die Antwort erreicht. Anders als Perceive, worespect_robots=trueeine nicht erlaubte URL mit403ablehnt, liefert Discover für eine Robots-Regel niemals403. Es verwirft die URL stillschweigend und meldet nichts.
Modi#
mode |
Was er tut |
|---|---|
sitemap |
Sitemap-Einträge aus robots.txt, geprüfte sitemap.xml (mit Index-Rekursion) und RSS/Atom-Feed-Seiten. Sofort, ohne Crawl. |
crawl |
Reiner HTTP-Breadth-First-Crawl ab dem Seed, der <a href>-Links aus dem rohen Markup sammelt. |
hybrid (Standard) |
Die deduplizierte Vereinigung von sitemap und crawl. |
Der Modus crawl ruft bis zu deinem vollen max_urls ab (bis zu
1,000), sodass eine große Website in einem Durchgang erfasst wird. Der
Crawl-Modus ist reines HTTP (kein Browser), daher bleibt das schnell.
Betreiber können die Obergrenze über die Umgebungsvariable
DISCOVER_CRAWL_MAX_PAGES senken, falls ein sehr großer Crawl je
begrenzt werden muss. pages_crawled in der Antwort gibt genau an, wie
viele GETs ausgeführt wurden.
Der Sitemap-Abruf verarbeitet gzip-komprimierte Sitemaps
(sitemap.xml.gz und jede als application/gzip ausgelieferte
Sitemap) und sendet realistische Browser-Header, sodass Websites hinter
einer WAF ihre Sitemap deutlich wahrscheinlicher zurückliefern statt
eines 403/503.
JavaScript-Rendering#
Die Modi crawl und hybrid lesen das rohe HTML, das ein Server
zurückgibt, sodass eine clientseitig gerenderte Single-Page-App, die
ihre Links im Browser aufbaut, für sie unsichtbar ist. render_js
aktiviert einen begrenzten Browser-Fallback, der diese Lücke schließt:
render_js |
Was er tut |
|---|---|
auto (Standard) |
Führt zuerst den HTTP-Crawl aus; rendert nur dann im Browser, wenn dieser eine bloße Hülle zurückliefert (eine oder keine URL), und sammelt dann die clientseitig eingefügten Links. |
always |
Führt immer den browser-gerenderten Crawl aus. |
never |
Bleibt strikt reines HTTP, das bisherige Verhalten. |
Der Fallback nutzt dasselbe gemeinsame Headless-Chrome wie
Perceive und ist auf wenige Seiten begrenzt,
damit der Aufruf innerhalb des Request-Timeouts bleibt. Von ihm
gefundene Links werden unter dem Schlüssel crawl_js in sources
gezählt. Er gilt nur für die Modi crawl und hybrid, denn der Modus
sitemap ist bereits browser-frei und unberührt.
Antwort#
POST /v2/discover liefert dieses Objekt direkt zurück, ohne
asynchronen Job und ohne zweiten Aufruf.
| Feld | Typ | Beschreibung |
|---|---|---|
url |
string |
Die von dir gesendete Seed-URL. |
mode |
string |
Der ausgeführte Modus: sitemap, crawl oder hybrid. |
total |
integer |
Anzahl der URLs in urls (nach Deduplizierung, Filterung und Obergrenze). |
urls |
string[] |
Die deduplizierte, normalisierte, begrenzte URL-Liste. Der Seed ist immer der erste Kandidat. |
pages_crawled |
integer |
Vom Crawl ausgelöste HTTP-GETs. 0 im reinen Modus sitemap. |
truncated |
boolean |
true, wenn mehr eindeutige URLs existierten, als max_urls erlaubte. |
robots_respected |
boolean |
Spiegelt den von dir gesendeten Wert von respect_robots. |
sources |
object |
Rohe URL-Anzahl pro Quelle vor Deduplizierung/Filterung, z. B. {"sitemap": 42, "crawl": 30}. Die Schlüssel umfassen sitemap, crawl, sitemap_apex (auf der Apex-Domain gefundene Sitemaps) und crawl_js (Links aus dem JavaScript-Render-Fallback). Die Zahlen überschneiden sich und summieren sich auf mehr als total. |
warnings |
string[] |
Nicht-fatale Hinweise: eine fehlende Sitemap, ein fehlgeschlagener Crawl, eine unerreichbare robots.txt. |
Die sources-Zahlen sind roh: Sie geben an, wie viele URLs jeder Pfad
erzeugt hat, bevor Normalisierung, Same-Domain-Prüfung, deine Filter
und Deduplizierung liefen. Sie summieren sich routinemäßig auf mehr
als total, weil der Modus hybrid dieselben Seiten sowohl über die
Sitemap als auch über den Crawl findet. Nutze sie, um zu sehen, welcher
Pfad die Karte trägt, nicht als Nachfilter-Summe.
Codebeispiele#
curl: Standard-Hybrid-Karte#
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: nur Sitemap, Blog-Seiten, begrenzt auf 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));
Ein gängiges Muster ist erst discovern, dann rendern: data.urls
nehmen und an den Perceive-Endpunkt übergeben,
mit einzelnen Aufrufen für eine Handvoll Seiten oder dessen Batch-Pfad
für die gesamte Liste.
Fehlerantworten#
| Status | Bedingung |
|---|---|
400 Bad Request |
Die URL ist nicht http(s), enthält eingebettete Zugangsdaten, hat keinen Hostnamen oder löst zu einer privaten, Loopback-, Link-Local- oder Cloud-Metadaten-Adresse auf (SSRF-Schutz). |
401 Unauthorized |
Fehlender oder ungültiger API-Schlüssel / JWT-Token. |
402 Payment Required |
Discover ist in deinem aktuellen Plan nicht freigeschaltet, oder dein monatliches Ops-Kontingent ist aufgebraucht. Jeder /v2/discover-Aufruf kostet eine Op. |
403 Forbidden |
/v2/discover ist nicht in den erlaubten Endpunkten des API-Schlüssels enthalten. |
422 Unprocessable Entity |
Die Request-Validierung ist fehlgeschlagen: ungültiger mode-Enum-Wert, max_urls außerhalb von 1 bis 1,000, max_depth außerhalb von 1 bis 5, mehr als 50 Include-/Exclude-Muster, ein fehlerhafter Regex oder eine url über 2,048 Zeichen. |
500 Internal Server Error |
Die URL-Ermittlung ist unerwartet fehlgeschlagen. Der Client erhält eine generische Meldung; die vollständigen Details gehen ausschließlich in die Server-Logs. |
Beachte, dass ein fehlgeschlagener Sitemap-Abruf oder ein Crawl-Fehler
keinen Fehlerstatus erzeugt. Diese werden zu Einträgen im
warnings-Array degradiert, und die Anfrage liefert trotzdem 200
mit allem, was gefunden wurde. Die vollständige Statuscode-Referenz
steht in der Fehlercode-Anleitung.
Limits#
| Limit | Wert |
|---|---|
| URL-Länge | 2,048 Zeichen |
max_urls |
1 bis 1,000 (Standard 100) |
max_depth |
1 bis 5 (Standard 2) |
include_patterns |
max. 50 Muster |
exclude_patterns |
max. 50 Muster |
| Abgerufene Seiten im Crawl-Modus | bis zu max_urls (max. 1,000; senkbar über DISCOVER_CRAWL_MAX_PAGES) |
| Request-Timeout | 300 Sekunden |
| Ops pro Aufruf | 1, berechnet gegen das einheitliche monatliche Kontingent |
Häufig gestellte Fragen#
Wie liste ich alle URLs einer Website mit einer API auf?#
Sende POST /v2/discover mit der URL der Website. Der Standardmodus hybrid kombiniert Sitemap-Parsing (robots.txt-Einträge, sitemap.xml mit Index-Rekursion, RSS/Atom-Feeds) mit einem Breadth-First-HTTP-Crawl und liefert in einer einzigen synchronen Antwort bis zu max_urls (1 bis 1,000, Standard 100) deduplizierte URLs.
Nutzt der Discover-Endpunkt einen Headless-Browser oder rendert er JavaScript?#
Standardmäßig läuft er über HTTP und rendert nur, wenn es sein muss. Die Option render_js steuert dies: Im Standardmodus "auto" bleibt Discover reines HTTP und rendert eine Seite nur dann im Browser, wenn der HTTP-Crawl eine bloße JavaScript-Hülle zurückliefert, wobei die clientseitig eingefügten Links gesammelt werden; "always" erzwingt den Browser-Crawl und "never" hält ihn strikt bei reinem HTTP. Der Modus sitemap bleibt eine schnelle, browser-freie Option für SEO-bewusste SPAs.
Wie viele Seiten ruft der Crawl-Modus tatsächlich ab?#
Der Crawl-Modus ruft bis zu deinem vollen max_urls ab (bis zu 1,000). Er bleibt reines HTTP und damit schnell; Betreiber können die Obergrenze über die Umgebungsvariable DISCOVER_CRAWL_MAX_PAGES senken. Jede abgerufene Seite trägt außerdem viele Links bei. Das Antwortfeld pages_crawled gibt genau an, wie viele HTTP-GETs ausgeführt wurden.
Kann ich filtern, welche URLs zurückkommen?#
Ja. include_patterns und exclude_patterns akzeptieren jeweils bis zu 50 Python-Regexe (Semantik von re.search, kein Glob), und respect_robots: true entfernt URLs, die laut der robots.txt der Website nicht erlaubt sind, aus der zurückgegebenen Liste.