Sitemap-Crawler-API#

Private Beta. Discover ist heute mit deinem normalen API-Schlüssel aufrufbar, in jedem Tarif einschließlich Founding, und zieht wie jeder andere Aufruf von deinem monatlichen Ops-Kontingent ab. Angekündigt oder allgemein verfügbar ist Discover nicht: Request- und Response-Formen können sich jederzeit ohne Vorankündigung ändern, und es gibt keine Stabilitäts- oder Supportzusage, baue also noch nichts Tragendes darauf. Die Roadmap steht unter Demnächst, und jedes Release wird im Changelog angekündigt.

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.

  1. 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 400 abgelehnt. Der Seed ist immer der erste Eintrag in seiner eigenen Karte.
  2. Aus Sitemaps sammeln. Im Modus sitemap oder hybrid liest Discover die robots.txt und ruft die dort deklarierten Sitemap:-URLs ab, prüft sitemap.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.
  3. Über HTTP crawlen. Im Modus crawl oder hybrid führt Discover ausgehend vom Seed einen Breadth-First-Crawl bis max_depth aus 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.
  4. 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 die max_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_robots wird zum Zeitpunkt der Ausgabefilterung durchgesetzt, nicht beim Abruf. Crawl4AI 0.8.9 hat kein natives Robots-Gate, daher kann im Modus crawl oder hybrid eine nicht erlaubte Seite trotzdem über HTTP abgerufen und erst danach verworfen werden, bevor sie die Antwort erreicht. Anders als Perceive, wo respect_robots=true eine nicht erlaubte URL mit 403 ablehnt, liefert Discover für eine Robots-Regel niemals 403. 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.