Distill
POST /v2/distill zieht strukturierte Daten aus einer oder mehreren URLs
heraus, passend zu einem Schema, das du angibst. Es läuft eine Engine mit
zwei Durchläufen: zuerst ein kostenloser CSS-Durchlauf (Crawl4AIs
JsonCssExtractionStrategy, gesteuert durch deine Selektoren), dann —
nur für die Felder, die der CSS-Durchlauf leer gelassen hat — ein
gedeckelter LLM-Durchlauf auf Anthropics claude-haiku-4-5. Das data
der Antwort kommt garantiert in genau der Form zurück, die du angefordert
hast. Es ist EnConverts Antwort auf Firecrawl /extract.
Hier ist der kleinste sinnvolle Aufruf. Sende eine URL und ein flaches
{field: description}-Schema, und erhalte die extrahierten Felder zurück:
curl -X POST https://api.enconvert.com/v2/distill \
-H "X-API-Key: sk_live_your_private_key" \
-H "Content-Type: application/json" \
-d '{
"urls": ["https://example.com/product/widget"],
"schema": {
"name": "the product name",
"price": "the listed price",
"in_stock": "whether it is in stock"
}
}'
Die Antwort enthält ein Ergebnis pro URL, die extrahierten data und
welche Stufe sie erzeugt hat:
{
"operation_id": "dst_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7",
"total": 1,
"completed": 1,
"failed": 0,
"results": [
{
"url": "https://example.com/product/widget",
"url_final": "https://example.com/product/widget",
"status": "completed",
"data": {
"name": "Widget Pro",
"price": "$49.00",
"in_stock": "yes"
},
"extraction_tier": "llm",
"fields_from_css": 0,
"fields_from_llm": 3,
"render_quality": 0.91,
"tokens": {"input": 4120, "output": 38},
"cost_cents": 0.45,
"warnings": []
}
],
"total_cost_cents": 0.45,
"warnings": []
}
Gleich vorweg erwähnenswert.
/v2/distillist ein V2-Endpunkt mit eigenem Kontingentzähler,distill_operations, bei dem eine Operation einer destillierten URL entspricht. V1-Konvertierungspläne enthalten keine Distill-Operationen — du brauchst einen V2-fähigen Plan, um es aufzurufen. Distill berechnet nur URLs, die abgeschlossen werden, sodass ein fehlgeschlagenes EnConvert-Rendering dich nie eine Einheit kostet. Siehe die Übersicht zur V2-Web-Intelligenz, wie die Zähler zusammenhängen, und die Preisseite für die Kontingente pro Stufe.
Endpunkte
| Methode | Pfad | Zweck |
|---|---|---|
POST |
/v2/distill |
Eine explizite URL-Liste destillieren oder zuerst die URLs einer Website ermitteln und jede gegen ein Schema destillieren. |
Content-Type: application/json.
Anders als perceive ist distill ein einzelner synchroner Endpunkt — es gibt keinen separaten GET-Neuabruf und keinen asynchronen Batch-Pfad. Jede URL wird sequenziell durch das gemeinsame Headless-Chrome-Singleton gerendert, und die vollständige Ergebnismenge kommt in einer Antwort zurück.
Authentifizierung
Authentifiziere dich mit einem privaten Schlüssel im X-API-Key-Header
für Server-zu-Server-Aufrufe. Das ist der Weg, den die Beispiele unten
verwenden.
X-API-Key: sk_live_your_private_key
Öffentliche Schlüssel mit einem JWT-Bearer-Token funktionieren ebenfalls,
über denselben Ablauf wie bei jedem anderen Endpunkt — erzeuge ein Token
mit deinem pk_-Schlüssel und sende es dann als
Authorization: Bearer <token>. Der vollständige Ablauf, einschließlich
Domain-Sperrung und Token-Erneuerung, steht im
Authentifizierungsleitfaden.
Jeder API-Schlüssel trägt eine Allowlist erlaubter Endpunkte. Steht
/v2/distill nicht auf der Liste des Schlüssels, wird die Anfrage mit
403 abgelehnt.
Wie distill funktioniert
Eine Anfrage destilliert eine Liste von URLs gegen ein Schema. Der Ablauf ist für jede URL derselbe:
- Die URL-Liste auflösen. Mit
urlsist die Liste genau das, was du gesendet hast (dedupliziert, Reihenfolge beibehalten). Mitdiscover_fromführt distill zuerst discover auf der Seed-URL aus — Parsen der Sitemap, Crawlen oder beides — und destilliert dann die ermittelten URLs bis zumax_pages. - Rendern. Jede URL wird einmal in Headless Chrome gerendert, durch
dieselbe Capture-Pipeline, die auch perceive
antreibt. Das Rendering wird auf SSRF geprüft und, falls
respect_robots=true, gegen dierobots.txtder Website abgeglichen. Es werden keine Artefakte in den Speicher hochgeladen — distill braucht nur das gerenderte DOM. - Durchlauf 1 — CSS (kostenlos). Wenn du ein
css_schemaangegeben hast, läuft der CSS-Extraktor über das gerenderte HTML und füllt jedes per Selektor adressierbare Feld ohne LLM-Kosten. Dieser Durchlauf ist auf 10 Sekunden zeitlich begrenzt; bei Zeitüberschreitung fällt die URL mit einer Warnung in den LLM-Durchlauf durch. - Durchlauf 2 — LLM (gedeckelt, nur bei Bedarf). Distill sammelt die
Schemafelder, die der CSS-Durchlauf fehlend oder leer gelassen hat, und
eskaliert nur diese Felder an
claude-haiku-4-5, unter harten Budgetdeckeln pro Aufruf und pro Periode. Wenn dein Plan keine LLM-Stufe hat, die Seite als blockiert gekennzeichnet wurde oder ein Budgetdeckel erreicht ist, wird der LLM-Durchlauf übersprungen und die fehlenden Felder kommen mit einer Warnung alsnullzurück. - Normalisieren. Das zusammengeführte Ergebnis wird auf exakt die
Schlüssel deines Schemas umgeformt — fehlende Skalare werden zu
null, fehlende Arrays werden zu[], und alle zusätzlichen Schlüssel werden verworfen. Die Formgarantie gilt unabhängig davon, was CSS oder das LLM erzeugt hat.
Der Kontingentzähler erhöht sich erst um eins, nachdem eine URL
abgeschlossen wurde. Render-Fehlschläge (SSRF-Ablehnung,
robots-Blockierung, ein abgestürztes Rendering) erzeugen eine
failed-Ergebniszeile und kosten kein Kontingent.
Anfrageparameter
Du musst genau eines von urls oder discover_from angeben, plus ein
schema. Beides oder keines zu senden ist ein 422.
Quelle — explizite URLs
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
urls |
string[] |
— | Explizite URLs zum Destillieren. Jede muss mit http:// oder https:// beginnen und höchstens 2.048 Zeichen lang sein. Maximal 50 URLs pro Anfrage (MAX_DISTILL_URLS). Schließt sich gegenseitig mit discover_from aus. |
Quelle — erst ermitteln, dann destillieren
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
discover_from |
object |
— | Zuerst die URLs einer Website ermitteln, dann jede destillieren. Schließt sich gegenseitig mit urls aus. Erfordert das Plan-Flag discover_enabled (andernfalls 402). |
discover_from.url |
string |
— | Seed-URL. Muss mit http:// oder https:// beginnen. Maximal 2.048 Zeichen. |
discover_from.mode |
string |
hybrid |
sitemap, crawl oder hybrid. Dieselben Modi wie beim discover-Endpunkt. |
discover_from.max_pages |
integer |
10 |
Obergrenze für ermittelte und destillierte URLs. 1–50 — jede ist ein vollständiges Rendering, daher durch MAX_DISTILL_URLS begrenzt. |
Schema (erforderlich)
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
schema |
object |
— | Die Ausgabeform, gesendet unter dem JSON-Schlüssel schema. Entweder ein JSON-Schema-Objekt ({"type": "object", "properties": {...}}) oder eine nachsichtige flache {field: description}-Map. Maximal 200 Eigenschaften auf oberster Ebene. Das data der Antwort entspricht garantiert dieser Form. Ein strukturell ungültiges Schema ist ein 422. Erforderlich. |
Das Schema ist der Vertrag. Wenn du ein JSON-Schema-Objekt sendest, liest
distill dessen properties; wenn du eine flache Map sendest, benennt jeder
Schlüssel ein Feld und jeder Wert ist die Beschreibung, die an das LLM
übergeben wird. So oder so kommt data mit genau den Schlüsseln des
Schemas auf oberster Ebene zurück.
CSS-Schema (optional)
Gib ein css_schema an, um Felder kostenlos vor jedem LLM-Aufruf zu
beantworten. Ohne es fällt jedes Feld direkt in den LLM-Durchlauf.
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
css_schema.baseSelector |
string |
— | CSS-Selektor für den sich wiederholenden Container; pro Treffer wird ein Datensatz extrahiert. 1–1.024 Zeichen. Erforderlich, wenn css_schema vorhanden ist. |
css_schema.fields |
CssField[] |
— | 1–128 Felddefinitionen, die aus jedem Container gelesen werden. Erforderlich. |
css_schema.name |
string |
"distill" |
Optionale Bezeichnung für das Schema. Maximal 128 Zeichen. |
css_schema.target_field |
string |
abgeleitet | Welche Ausgabe-Eigenschaft auf oberster Ebene die CSS-Datensätze füllen — eine Array-Eigenschaft erhält die vollständige Datensatzliste, eine Skalar-/Objekt-Eigenschaft erhält den ersten Datensatz. Wenn weggelassen, leitet distill es ab, sofern das Schema genau eine Array-Eigenschaft hat. Maximal 128 Zeichen. |
Jeder Eintrag in fields ist ein CssField:
| Feld | Typ | Standard | Beschreibung |
|---|---|---|---|
name |
string |
— | Ausgabeschlüssel für dieses Feld. 1–128 Zeichen. Erforderlich. |
type |
string |
— | Eines von text, attribute, html, regex, nested, list, nested_list. Erforderlich. |
selector |
string |
null |
CSS-Unterselektor. Optional für Blatt-Typen (text/attribute/html/regex); erforderlich für nested/list/nested_list. Maximal 1.024 Zeichen. |
attribute |
string |
null |
Name des zu lesenden Attributs. Erforderlich, wenn type attribute ist. Maximal 128 Zeichen. |
pattern |
string |
null |
Regex-Muster. Erforderlich, wenn type regex ist. Wird am Edge kompiliert; ein Muster mit verschachtelten, re-quantifizierten Gruppen (eine ReDoS-Form wie (a+)+) wird mit 422 abgelehnt. Maximal 1.024 Zeichen. |
default |
beliebig | null |
Wert, wenn der Selektor nichts trifft. |
transform |
string |
null |
Eines von lowercase, uppercase, strip. |
fields |
CssField[] |
null |
Kindfelder, für nested/list/nested_list. Maximal 64 Kinder; maximale Gesamtverschachtelungstiefe 5. |
Erwähnenswert: Der Feldtyp computed aus Crawl4AI wird bewusst nicht
akzeptiert. Seine Ausdrucksform führt eval auf Aufrufer-Eingaben aus, und
seine Callable-Form kann eine JSON-Grenze nicht überschreiten, daher zählt
distill nur die sieben sicheren Typen oben auf.
Render-Stellschrauben
Distill rendert nur das DOM und stellt daher nur eine kleine Teilmenge der perceive-Render-Optionen bereit.
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
wait_for |
string |
null |
Nach der Navigation auf einen CSS-Selektor oder einen JS-Ausdruck warten ("js:window.dataReady === true"). Maximal 1.024 Zeichen. |
wait_timeout_ms |
integer |
30000 |
Wie lange wait_for warten darf, in Millisekunden. 0–60.000. |
headers |
object |
null |
Benutzerdefinierte Request-Header für das Rendering. |
cookies |
array |
null |
Cookies, die vor der Navigation injiziert werden. |
respect_robots |
boolean |
false |
Bei true wird eine durch die robots.txt der Website verbotene URL abgelehnt und das Ergebnis dieser URL als failed markiert. |
Antwort
POST /v2/distill gibt eine DistillResponse zurück:
| Feld | Typ | Beschreibung |
|---|---|---|
operation_id |
string |
Undurchsichtige ID (dst_...). Gib sie beim Support an. |
total |
integer |
Anzahl der verarbeiteten URLs (Zeilen in results). |
completed |
integer |
URLs, die gerendert und ein data-Objekt erzeugt haben. |
failed |
integer |
URLs, deren Rendering abgelehnt wurde oder abgestürzt ist. |
results |
object[] |
Ein DistillItemResult pro URL — siehe unten. |
total_cost_cents |
number |
Summe der LLM-Kosten pro URL über die gesamte Anfrage, in Cent. |
warnings |
string[] |
Hinweise auf Anfrageebene (z. B. Kontingent mitten in der Liste erschöpft, Fehler beim discover-Crawl). |
Jeder Eintrag in results ist ein DistillItemResult:
| Feld | Typ | Beschreibung |
|---|---|---|
url |
string |
Die URL, die du gesendet (oder ermittelt) hast. |
url_final |
string |
Die URL nach Weiterleitungen. Wird bei einer failed-Zeile weggelassen. |
status |
string |
completed oder failed. |
data |
object |
Die extrahierten Daten, normalisiert auf exakt die Schlüssel deines Schemas. null bei einer failed-Zeile. |
extraction_tier |
string |
css (nur CSS), llm (nur LLM), mixed (beide trugen bei) oder none (nichts gefunden). |
fields_from_css |
integer |
Anzahl der Felder, die der CSS-Durchlauf gefüllt hat. |
fields_from_llm |
integer |
Anzahl der Felder, die der LLM-Durchlauf gefüllt hat. |
render_quality |
number |
0.0–1.0. Niedrige Werte deuten auf Anti-Bot-Challenges oder Login-Hürden hin. |
tokens |
object |
{input, output} verwendete LLM-Tokens. Null, sofern der LLM-Durchlauf nicht lief. |
cost_cents |
number |
LLM-Kosten in Cent für diese URL. Null, sofern der LLM-Durchlauf nicht lief. |
error |
string |
Nur gesetzt, wenn status failed ist. Eine generische Meldung — interne Render-Details bleiben serverseitig. |
warnings |
string[] |
Hinweise pro URL: eine CSS-Zeitüberschreitung, ein übersprungener LLM-Durchlauf, ein erreichter Budgetdeckel. |
Um es klar zu sagen: Die Antwort enthält keine signierten Download-URLs und
keine gespeicherten Artefakte. Distill gibt die strukturierten data inline
zurück und sonst nichts — wenn du auch das Markdown, HTML, einen Screenshot
oder ein PDF der Seite willst, dafür ist perceive
da.
Das Zwei-Durchlauf-Kostenmodell
Der CSS-Durchlauf ist kostenlos. Der LLM-Durchlauf kostet Geld, daher startet distill ihn so eng wie möglich und deckelt ihn aus mehreren Richtungen.
Er eskaliert nur die fehlenden Felder. Nach dem CSS-Durchlauf
berechnet distill, welche Schemafelder noch leer sind — ein Skalar, der als
null/"" zurückkam, ein Array, das leer zurückkam, oder ein Array, dessen
Elemente ein deklariertes Unterfeld vermissen lassen. Nur diese Feldnamen
gehen in ein reduziertes Schema für den LLM-Aufruf, was Prompt und Kosten
minimal hält.
Er überspringt den LLM-Durchlauf vollständig, wenn eine dieser Bedingungen zutrifft, und gibt stattdessen das CSS-only-Ergebnis mit einer Warnung zurück, anstatt zu viel auszugeben:
- Dein Plan hat keine LLM-Stufe (
llm_extraction_enabledplus eine nicht-none-agent_model_tier). - Die
render_qualityder Seite hat sie als durch Anti-Bot-Schutz blockiert gekennzeichnet. - Das LLM-Budget pro Anfrage für diesen Aufruf ist erreicht oder der Budgetdeckel pro Periode ist erreicht.
Die Budgetdeckel sind geschichtet:
| Deckel | Wert | Geltungsbereich |
|---|---|---|
| Pro Aufruf | $0.05 (PER_REQUEST_CAP_CENTS) |
Schlimmstfall-Prognosekosten eines LLM-Aufrufs. Darüber → übersprungen vor jeglichem Netzwerk-I/O. |
| Pro Anfrage | $0.50 (_REQUEST_LLM_BUDGET_CENTS) |
Gesamte LLM-Ausgaben über alle URLs in einem /v2/distill-Aufruf. Verbleibende URLs liefern nur CSS. |
| Eskalationen pro Anfrage | 50 (_MAX_LLM_ESCALATIONS) |
Höchstens ein LLM-Aufruf pro URL, hart gedeckelt. |
| Pro Periode | $5 Standard, $20 ab Pro | ch_usage_periods.llm_cost_cents für deinen Abrechnungszeitraum (usage.reserve_llm_budget). |
Hinweis. Das Budget pro Periode wird vor dem Aufruf atomar reserviert und danach auf die tatsächlichen Kosten heruntergerechnet, sodass gleichzeitige Aufrufe den Deckel nicht gemeinsam überschreiten können. Ein Projekt ohne aktive Zeitraumzeile schlägt sicher fehl — Ausgaben, die EnConvert nicht zuordnen kann, sind Ausgaben, die es nicht tätigt. Wenn ein Deckel erreicht ist, kommen die betroffenen Felder als
nullmit einer Warnung zurück; die Anfrage ist trotzdem erfolgreich.
Wenn der LLM-Durchlauf läuft, meldet extraction_tier llm oder mixed,
und tokens und cost_cents melden, was er gekostet hat. Wenn er nicht
läuft, sind beide null.
CSS-Datensätze auf dein Schema abbilden
Der häufige Fall ist eine Listenseite: eine sich wiederholende Zeile und ein
Ausgabeschema mit einer Array-Eigenschaft, die die Zeilen aufnimmt. Gib
distill ein css_schema, dessen baseSelector auf die Zeile passt und
dessen fields die Spalten lesen, und es füllt das Array kostenlos:
curl -X POST https://api.enconvert.com/v2/distill \
-H "X-API-Key: sk_live_your_private_key" \
-H "Content-Type: application/json" \
-d '{
"urls": ["https://example.com/products"],
"schema": {
"type": "object",
"properties": {
"products": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"price": {"type": "string"},
"sku": {"type": "string"}
}
}
}
}
},
"css_schema": {
"baseSelector": ".product-card",
"target_field": "products",
"fields": [
{"name": "name", "type": "text", "selector": ".title"},
{"name": "price", "type": "text", "selector": ".price"},
{"name": "sku", "type": "attribute",
"selector": ".product-card", "attribute": "data-sku"}
]
}
}'
Wie Datensätze auf dem Schema landen:
target_fieldauf eine Array-Eigenschaft gesetzt → diese Eigenschaft erhält die vollständige Datensatzliste.target_fieldauf eine Skalar-/Objekt-Eigenschaft gesetzt → sie erhält den ersten Datensatz.target_fieldweggelassen, Schema hat genau eine Array-Eigenschaft → distill leitet sie ab und füllt diese Eigenschaft.- Andernfalls → der erste Datensatz wird als einzelnes flaches Objekt behandelt und seine passenden Schlüssel werden auf die oberste Ebene gehoben.
Wenn CSS das Array füllt, aber einigen Elementen ein deklariertes Unterfeld
fehlt — sagen wir, sku fehlt auf der Hälfte der Karten — eskaliert distill
products an den LLM-Durchlauf, um die Lücken zu füllen. Das ist der
Zwei-Durchlauf-Unterschied gegenüber einem reinen Scraper: strukturiert, wo
es kann, modellgestützt, wo es muss.
Codebeispiele
curl — flaches Schema, nur LLM
curl -X POST https://api.enconvert.com/v2/distill \
-H "X-API-Key: sk_live_your_private_key" \
-H "Content-Type: application/json" \
-d '{
"urls": ["https://example.com/article"],
"schema": {
"headline": "the article headline",
"author": "the author name",
"published": "the publish date"
}
}'
curl — erst ermitteln, dann destillieren
curl -X POST https://api.enconvert.com/v2/distill \
-H "X-API-Key: sk_live_your_private_key" \
-H "Content-Type: application/json" \
-d '{
"discover_from": {
"url": "https://example.com/blog",
"mode": "sitemap",
"max_pages": 25
},
"schema": {
"title": "the post title",
"summary": "a one-line summary"
}
}'
Python
import requests
response = requests.post(
"https://api.enconvert.com/v2/distill",
headers={"X-API-Key": "sk_live_your_private_key"},
json={
"urls": ["https://example.com/product/widget"],
"schema": {
"name": "the product name",
"price": "the listed price",
"in_stock": "whether it is in stock",
},
},
)
response.raise_for_status()
result = response.json()
for item in result["results"]:
if item["status"] == "completed":
print(item["url"], "->", item["data"])
else:
print(item["url"], "FAILED:", item["error"])
print("total cost (cents):", result["total_cost_cents"])
Node.js
const res = await fetch("https://api.enconvert.com/v2/distill", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "sk_live_your_private_key"
},
body: JSON.stringify({
urls: ["https://example.com/product/widget"],
schema: {
name: "the product name",
price: "the listed price",
in_stock: "whether it is in stock"
}
})
});
const result = await res.json();
for (const item of result.results) {
if (item.status === "completed") {
console.log(item.url, "->", item.data);
} else {
console.log(item.url, "FAILED:", item.error);
}
}
console.log("total cost (cents):", result.total_cost_cents);
Plan-Gating
Distill-Operationen werden auf ihrem eigenen distill_operations-Zähler
gemessen, getrennt von V1-Konvertierungen und vom
perceive-Zähler. Eine Operation entspricht einer
destillierten URL, und nur URLs, die abgeschlossen werden, werden gezählt.
V1-Konvertierungspläne enthalten kein Distill-Kontingent — du brauchst einen
V2-fähigen Plan.
Der schemagesteuerte LLM-Durchlauf (claude-haiku-4-5) ist ein weiteres
Plan-Gate: Er läuft nur, wenn dein Plan llm_extraction_enabled und eine
nicht-none-Agent-Modellstufe trägt. Ohne das gibt distill nur
CSS-Ergebnisse zurück und vermerkt die übersprungenen Felder in warnings.
Das LLM-Budget pro Periode beträgt $5 auf der Standardstufe und $20 ab Pro.
discover_from zu verwenden erfordert zusätzlich das Plan-Flag
discover_enabled — andernfalls wird die Anfrage mit 402 abgelehnt,
sodass ein reiner Distill-Plan discover nicht kostenlos über diesen Weg
erreichen kann.
distill_operations-Kontingente pro Stufe und die Pläne, die die LLM-Stufe
enthalten, stehen auf der Preisseite.
Fehlerantworten
| Status | Bedingung |
|---|---|
400 Bad Request |
Eine URL (oder der discover_from-Seed) löst zu einer privaten, Loopback- oder Link-Local-Adresse auf, hat keinen Hostnamen oder besteht den SSRF-Screen anderweitig nicht. Wird pro URL beim Rendern ausgelöst. |
401 Unauthorized |
Fehlender oder ungültiger API-Schlüssel / JWT-Token. |
402 Payment Required |
Distill ist nicht in deinem aktuellen Plan, dein monatliches distill_operations-Kontingent ist erschöpft, oder discover_from wurde ohne das Plan-Flag discover_enabled gesendet. |
403 Forbidden |
/v2/distill ist nicht in den erlaubten Endpunkten des API-Schlüssels. |
422 Unprocessable Entity |
Kein schema, beide oder keines von urls/discover_from, ein strukturell ungültiges Schema, über 200 Schemaeigenschaften, ein ungültiges CssField (fehlendes attribute/pattern/fields für seinen Typ, ein nicht kompilierbarer oder ReDoS-anfälliger Regex) oder eine CSS-Feldverschachtelung tiefer als 5. |
500 Internal Server Error |
Die Orchestrierung ist unerwartet fehlgeschlagen. Die Meldung enthält die operation_id, die du beim Support angeben kannst. |
Ein paar Statushinweise, die man auseinanderhalten sollte: Eine einzelne
URL, deren Rendering wegen SSRF abgelehnt wird, zeigt nur dann ein 400,
wenn sie der Seed einer discover_from-Anfrage ist; bei einer expliziten
urls-Liste wird eine Render-Ablehnung pro URL zu einer
failed-Ergebniszeile, statt die gesamte Anfrage scheitern zu lassen. Ein
LLM-Budgetdeckel ist nie ein Fehler — er degradiert zu einem
CSS-only-Ergebnis mit einer Warnung. Die vollständige
Statuscode-Referenz steht im Fehlercode-Leitfaden.
Limits
| Limit | Wert |
|---|---|
URLs pro Anfrage (urls) |
50 (MAX_DISTILL_URLS) |
discover_from.max_pages |
1–50 |
| URL-Länge | 2.048 Zeichen |
| Schemaeigenschaften auf oberster Ebene | 200 (MAX_SCHEMA_PROPERTIES) |
css_schema.fields |
1–128 |
CssField.fields-Kinder |
64 |
| CSS-Feldverschachtelungstiefe | 5 (MAX_CSS_FIELD_DEPTH) |
wait_for-Länge |
1.024 Zeichen |
wait_timeout_ms |
0–60.000 ms |
| CSS-Durchlauf-Zeitüberschreitung | 10 Sekunden pro URL |
| LLM-Deckel pro Aufruf | $0.05 |
| LLM-Deckel pro Anfrage | $0.50 |
| LLM-Eskalationen pro Anfrage | 50 |
| LLM-Deckel pro Periode | $5 Standard / $20 ab Pro |
Monatliche distill_operations |
Planabhängig — siehe Preise |