Perceive

POST /v2/perceive rendert eine URL einmal in einem echten Browser und liefert jede Ausgabe zurück, die du aus diesem einen Render anforderst: Markdown, bereinigtes oder rohes HTML, einen Screenshot, ein PDF, das Link- und Bildverzeichnis sowie strukturierte Daten (Seitenmetadaten, JSON-LD, Überschriften, Tabellen). Es ersetzt einen Stapel separater Aufrufe — url-to-markdown, url-to-screenshot, url-to-pdf, plus dein eigenes Scraping — durch eine einzige Anfrage.

Hier ist der kleinste nützliche Aufruf. Sende eine URL, erhalte sauberes Markdown und die strukturierten Metadaten der Seite zurück:

curl -X POST https://api.enconvert.com/v2/perceive \
  -H "X-API-Key: sk_live_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/pricing",
    "outputs": ["markdown", "structured"]
  }'

Die Antwort enthält eine vorsignierte Download-URL für die Markdown-Datei und den strukturierten Block inline:

{
    "operation_id": "per_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7",
    "status": "completed",
    "url": "https://example.com/pricing",
    "url_final": "https://example.com/pricing",
    "content_hash": "9f2b8c1a...d4e5",
    "render_quality": 0.93,
    "cache_hit": false,
    "outputs": {
        "markdown": {
            "url": "https://spaces.example.com/...signed...",
            "object_key": "env/files/4127/v2-perceive/per_3f9a..._markdown.md",
            "size_bytes": 8421,
            "content_type": "text/markdown; charset=utf-8",
            "expires_in": 900
        }
    },
    "structured": {
        "metadata": {
            "title": "Pricing",
            "description": "Simple, usage-based pricing."
        },
        "structured_data": [
            {"@type": "Product", "name": "Pro", "offers": {"price": "99"}}
        ]
    },
    "extraction_tier": "heuristic",
    "tokens": {"input": 0, "output": 0},
    "cost_cents": 0.0,
    "duration_ms": 6230,
    "warnings": []
}

Gleich vorweg erwähnenswert. /v2/perceive ist ein V2-Endpunkt mit eigenem Kontingentzähler. V1-Konvertierungspläne enthalten keine V2-perceive-Operationen — du brauchst einen V2-inklusiven Plan, um ihn aufzurufen. Siehe die Preisseite für die Kontingente pro Stufe.


Endpunkte

Method Path Zweck
POST /v2/perceive Eine einzelne URL perceiven und die angeforderten Ausgaben zurückgeben.
GET /v2/perceive/{operation_id} Eine vergangene Operation mit frisch signierten Download-URLs erneut abrufen.
POST /v2/perceive/batch Bis zu 1.000 URLs perceiven, die einen gemeinsamen Satz von Optionen teilen.
GET /v2/perceive/batch/{job_id} Status und Ergebnisse pro URL eines Batches abfragen.

Content-Type: application/json bei jedem POST.


Authentifizierung

Authentifiziere dich mit einem privaten Schlüssel im X-API-Key-Header für Server-zu-Server-Aufrufe. Diesen Weg nutzen die Beispiele unten.

X-API-Key: sk_live_your_private_key

Öffentliche Schlüssel mit einem JWT-Bearer-Token funktionieren ebenfalls, über denselben Ablauf wie jeder andere Endpunkt — erzeuge ein Token mit deinem pk_-Schlüssel und sende es dann als Authorization: Bearer <token>. Der vollständige Ablauf, inklusive Domain-Sperre und Token-Aktualisierung, steht in der Authentifizierungs-Anleitung.

Jeder API-Schlüssel trägt eine Allowlist erlaubter Endpunkte. Wenn /v2/perceive nicht auf der Liste des Schlüssels steht, wird die Anfrage mit 403 abgelehnt.


Wie perceive funktioniert

Eine Anfrage löst einen Browser-Render über einen gemeinsam genutzten Headless-Chrome-Singleton aus und materialisiert dann jede Ausgabe aus diesem Render. Du zahlst nie zweimal für dieselbe Seite in einem einzigen Aufruf.

  1. Render. Die Seite lädt in Headless Chrome. Cookie-Banner werden weggeklickt, die Seite wird gescrollt, um lazy-geladene Inhalte auszulösen, Sticky-Header werden behandelt und Bilder bekommen Zeit zum Laden — dieselbe Capture-Pipeline, die den url-to-pdf-Endpunkt antreibt.
  2. Materialisieren. Aus dem gerenderten DOM baut perceive, was auch immer du in outputs aufgelistet hast: Markdown, bereinigtes/rohes HTML, Links, Bilder, einen Screenshot, ein PDF.
  3. Extrahieren. Wenn du structured-Ausgabe angefordert hast, führt perceive einen heuristischen Durchlauf für Seitenmetadaten, JSON-LD, Überschriften und Tabellen durch. Wenn du außerdem ein schema sendest und dein Plan die LLM-Stufe trägt, füllt ein Anthropic Claude Haiku-Modell das Schema, wenn der heuristische Durchlauf zu kurz greift.
  4. Bewerten. Ein Render-Qualitätswert (0.0–1.0) markiert Seiten, die durch Anti-Bot-Schutz blockiert oder hinter einer Login-Wand verborgen wirken, sodass du einen echten Render von einer Challenge-Seite unterscheiden kannst.

Binär- und Textausgaben (Markdown, HTML, Screenshots, PDFs, das Link- und Bild-JSON) werden in den Speicher hochgeladen und als vorsignierte URLs zurückgegeben, die nach 15 Minuten ablaufen. Der structured-Block wird inline im JSON zurückgegeben. Rufe jede Operation mit GET /v2/perceive/{operation_id} erneut ab, um einen frischen Satz signierter URLs zu erhalten.


Anfrageparameter

Kern

Parameter Type Default Beschreibung
url string Die zu perceivende Seite. Muss mit http:// oder https:// beginnen. Maximal 2.048 Zeichen. Erforderlich.
outputs string[] ["markdown", "structured"] Welche Ausgaben erzeugt werden. Siehe Outputs.
extract string[] [] Welche strukturierten Felder gezogen werden, wenn structured in outputs steht. Siehe Structured extraction.
schema object null Ein JSON-Schema, das die Felder beschreibt, die du extrahieren möchtest. Löst die LLM-Extraktionsstufe auf Plänen aus, die sie enthalten.
cache_mode string "enabled" enabled, bypass oder refresh. Siehe Caching.

Outputs

outputs akzeptiert jede Kombination dieser Namen:

Output Zurückgegeben als Was du bekommst
markdown signierte URL Sauberes Markdown aus dem Hauptinhalt, Links und Bilder zu absoluten URLs aufgelöst.
markdown_fit signierte URL "Fit"-Markdown — eine beschnittene, dichtere Variante, abgestimmt auf LLM-Kontextfenster.
html_cleaned signierte URL Das gerenderte HTML mit entfernten Skripten, Styles und Boilerplate.
html_raw signierte URL Das vollständige gerenderte HTML genau so, wie der Browser es erzeugt hat.
screenshot signierte URL Ein Viewport-PNG in der angeforderten (oder Standard-)Viewport-Größe.
screenshot_full_page signierte URL Ein Vollseiten-PNG, das die gesamte Scrollhöhe erfasst.
pdf signierte URL Ein PDF der Seite. Akzeptiert die vollständige pdf_options-Fläche (siehe unten).
links signierte URL Ein JSON-Array jedes gefundenen Links, mit absoluten URLs und Ankertext.
images signierte URL Ein JSON-Array jedes Bildes, mit absolutem src und alt-Text.
structured inline JSON Strukturierte Daten, die aus der Seite extrahiert wurden (das structured-Antwortfeld).

Rendern und Warten

Parameter Type Default Beschreibung
viewport object 1920 x 1080 {"width": <int>, "height": <int>}. Breite 320–3840, Höhe 240–2160.
mobile boolean false In einem mobilen Viewport rendern (390 x 844), sofern viewport nicht explizit gesetzt ist.
wait_for string null Nach der Navigation auf einen CSS-Selektor (".price" oder "css:.price") oder einen JS-Ausdruck ("js:window.dataReady === true") warten.
wait_timeout_ms integer 30000 Wie lange wait_for warten darf, in Millisekunden. 0–60.000. Ein Timeout wird zu einer Warnung herabgestuft; die Seite wird so erfasst, wie sie ist.
js_code string null JavaScript, das nach der Navigation auf der Seite ausgeführt wird. Maximal 20.000 Zeichen. Ein Fehler wird zu einer Warnung, nicht zu einem Fehlschlag.
block_resources string[] [] Ressourcentypen, die vor dem Laden abgebrochen werden. Beliebige von image, media, font, stylesheet, script, xhr, fetch, websocket, manifest, other. Nützlich für schnellere, reine Text-Renders.
respect_robots boolean false Wenn true, wird eine durch die robots.txt der Seite verbotene URL mit 403 abgelehnt.
pdf_options object null Seitenformat, Ränder, Kopf- und Fußzeilen, Skalierung und Ausrichtung für pdf-Ausgabe. Dasselbe Objekt wie url-to-pdf. Ohne pdf_options erzeugt perceive eine einzige durchgehende Seite, byteidentisch zu V1 url-to-pdf.

Authentifizierte und benutzerdefinierte Anfragen

Parameter Type Default Beschreibung
auth object null HTTP Basic Auth für die Zielseite: {"username": "...", "password": "..."}.
cookies array null Cookies, die vor der Navigation eingespeist werden. Maximal 50. Jedes braucht name, value und entweder domain oder url.
headers object null Benutzerdefinierte Anfrage-Header. Maximal 20. Blockierte Namen: host, content-length, transfer-encoding, connection, upgrade, te, trailer.
Reserviert, noch nicht aktiv. proxy_url (Business+), geolocation und action_chain werden vom Anfrageschema akzeptiert, geben heute aber 422 zurück. Sie kommen in einer späteren Version; sie jetzt zu senden sagt dir genau, welcher Regler noch nicht bereit ist, statt ihn stillschweigend zu ignorieren.

Structured extraction

Wenn structured in outputs steht, steuert die extract-Liste, welche Felder perceive zieht. Fordere nichts an, und es fällt auf metadata und structured_data zurück.

extract-Wert Feld in structured Status
metadata metadata Live
structured_data structured_data (JSON-LD) Live
headings headings Live
tables tables Live
main_content main_content (Text, gedeckelt bei 50.000 Zeichen) Live
all erweitert sich zu jedem Live-Feld oben Live
prices Noch nicht — gibt eine Warnung zurück, ausgelassen
contacts Noch nicht — gibt eine Warnung zurück, ausgelassen
technologies Noch nicht — gibt eine Warnung zurück, ausgelassen

Um es klar zu sagen: prices, contacts und technologies sind reservierte Namen. Fordere heute einen davon an, und es gibt keinen Fehler — er landet im warnings-Array und wird aus structured entfernt.

Schema-gesteuerte Extraktion

Sende ein schema, um bestimmte Felder in structured.extracted zu ziehen:

{
    "url": "https://example.com/product/widget",
    "outputs": ["markdown", "structured"],
    "schema": {
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "price": {"type": "number"},
            "in_stock": {"type": "boolean"}
        }
    }
}

Die LLM-Extraktionsstufe (Anthropic Claude Haiku) füllt das Schema und greift nur, wenn alle dieser Bedingungen zutreffen: du hast ein schema gesendet, dein Plan trägt die LLM-Stufe (Starter und aufwärts), die Seite wurde nicht als blockiert bewertet, und der heuristische Durchlauf ließ Schemafelder leer. Wenn sie läuft, ist extraction_tier gleich "llm", und tokens und cost_cents melden, was diese Extraktion gekostet hat; andernfalls ist extraction_tier gleich "heuristic" und beide sind null.

Hinweis. Schema-Extraktion ist fest gedeckelt, um deine Rechnung zu schützen: eine einzelne Extraktion ist pro Anfrage gedeckelt, und die tägliche Ausgabe pro Projekt ist durch den Plan gedeckelt. Wird ein Deckel erreicht, gibt perceive das heuristische Ergebnis mit einem Hinweis in warnings zurück, statt zu überzahlen. Auf einem Plan ohne die LLM-Stufe bekommst du nur heuristische structured-Daten.


Antwort

Sowohl POST /v2/perceive als auch GET /v2/perceive/{operation_id} geben dasselbe Objekt zurück.

Field Type Beschreibung
operation_id string Opake ID (per_...). Verwende sie mit dem GET-Endpunkt und nenne sie dem Support.
status string queued, processing, completed oder failed.
url string Die URL, die du gesendet hast.
url_final string Die URL nach Weiterleitungen.
content_hash string SHA-256 der gerenderten Seite. Treibt den 1-Stunden-Cache an.
render_quality number 0.0–1.0. Niedrige Werte markieren Anti-Bot-Challenges oder Login-Wände.
cache_hit boolean true, wenn das Ergebnis aus dem Cache statt aus einem frischen Render kam.
outputs object Zuordnung von Ausgabename zu {url, object_key, size_bytes, content_type, expires_in}. Signierte URLs laufen in 900 Sekunden ab.
structured object Inline strukturierte Daten, vorhanden, wenn structured angefordert wurde.
extraction_tier string heuristic, css oder llm.
tokens object {input, output} verwendete LLM-Token. Null, sofern die LLM-Stufe nicht lief.
cost_cents number LLM-Kosten in Cent für diese Operation. Null, sofern die LLM-Stufe nicht lief.
duration_ms integer End-to-End-Render-Zeit.
error string Nur gesetzt, wenn status gleich failed ist.
warnings string[] Nicht-fatale Hinweise: ein wait_for-Timeout, ein übersprungenes Extract, ein Blocked-Page-Flag.

Eine Operation abrufen

Signierte URLs laufen nach 15 Minuten ab. Um eine Ausgabe später herunterzuladen, rufe die Operation erneut ab — perceive signiert jede URL aus den gespeicherten Object Keys neu. Es findet kein erneuter Render statt, also verbraucht dies kein Kontingent.

curl https://api.enconvert.com/v2/perceive/per_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7 \
  -H "X-API-Key: sk_live_your_private_key"

Eine unbekannte Operations-ID oder eine, die zu einem anderen Projekt gehört, gibt 404 zurück — Existenz wird nie projektübergreifend preisgegeben.


Batch-Perception

POST /v2/perceive/batch perceived eine Liste von URLs, die einen gemeinsamen options-Block teilen. Jede URL wird durch dieselbe Pipeline wie ein Einzelaufruf gerendert und erzeugt ihre eigene Operationszeile.

curl -X POST https://api.enconvert.com/v2/perceive/batch \
  -H "X-API-Key: sk_live_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": [
      "https://example.com/a",
      "https://example.com/b",
      "https://example.com/c"
    ],
    "options": {"outputs": ["markdown"]},
    "output_mode": "manifest"
  }'

Batches mit 10 URLs oder weniger laufen inline und antworten mit 200, wobei jedes Ergebnis befüllt ist. Größere Batches antworten mit 202 und einer job_id; die URLs werden eine nach der anderen abgearbeitet, und du fragst die Ergebnisse ab:

curl https://api.enconvert.com/v2/perceive/batch/{job_id} \
  -H "X-API-Key: sk_live_your_private_key"

Die Batch-Antwort meldet den aggregierten Fortschritt und trägt ein vollständiges perceive-Ergebnis pro URL, sobald gerendert:

{
    "job_id": "bat_8c1a...",
    "status": "partial",
    "output_mode": "manifest",
    "total": 3,
    "completed": 2,
    "failed": 1,
    "pending": 0,
    "items": [
        {"operation_id": "per_...", "status": "completed", "url": "https://example.com/a"},
        {"operation_id": "per_...", "status": "completed", "url": "https://example.com/b"},
        {"operation_id": "per_...", "status": "failed", "url": "https://example.com/c"}
    ]
}

status ist queued, processing, completed, failed oder partial (einige URLs erfolgreich, einige fehlgeschlagen). Setze output_mode auf zip, um jedes Artefakt in ein einziges ZIP zu bündeln, das unter dem zip-Feld zurückgegeben wird, sobald der Batch fertig ist. Batch-Zugang und die maximale Batch-Größe sind plangebunden; siehe die Preisseite.


Caching

cache_mode steuert, wie perceive seinen 1-Stunden-Ergebnis-Cache behandelt, verschlüsselt nach deinem Projekt, der URL und den render-beeinflussenden Anfrageoptionen.

cache_mode Verhalten
enabled (Standard) Ein zwischengespeichertes Ergebnis zurückgeben, wenn eine identische Anfrage innerhalb der letzten Stunde gerendert wurde. cache_hit ist true, cost_cents ist 0.
bypass Den Cache überspringen und frisch rendern.
refresh Frisch rendern und den Cache-Eintrag ersetzen.

Erwähnenswert: ein Cache-Treffer zählt trotzdem als eine perceive-Operation gegen dein Monatskontingent. Das Kontingent misst Operationen, nicht Browser-Renders — der Cache spart dir Render-Zeit, nicht Kontingent.


Code-Beispiele

curl — Nur Markdown

curl -X POST https://api.enconvert.com/v2/perceive \
  -H "X-API-Key: sk_live_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/blog/post",
    "outputs": ["markdown"]
  }'

curl — Markdown plus strukturierte Daten

curl -X POST https://api.enconvert.com/v2/perceive \
  -H "X-API-Key: sk_live_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/pricing",
    "outputs": ["markdown", "structured"],
    "extract": ["metadata", "structured_data", "tables"]
  }'

curl — Vollständige Ausgaben plus PDF

curl -X POST https://api.enconvert.com/v2/perceive \
  -H "X-API-Key: sk_live_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/report",
    "outputs": ["markdown", "html_cleaned", "screenshot_full_page", "pdf"],
    "pdf_options": {"format": "A4", "print_background": true}
  }'

Python

import requests

response = requests.post(
    "https://api.enconvert.com/v2/perceive",
    headers={"X-API-Key": "sk_live_your_private_key"},
    json={
        "url": "https://example.com/pricing",
        "outputs": ["markdown", "structured"],
        "extract": ["metadata", "tables"],
    },
)
response.raise_for_status()
data = response.json()

# Download the Markdown artifact from its signed URL
markdown_url = data["outputs"]["markdown"]["url"]
markdown_text = requests.get(markdown_url).text

print(data["structured"])
print(markdown_text)

Node.js

const res = await fetch("https://api.enconvert.com/v2/perceive", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-API-Key": "sk_live_your_private_key"
    },
    body: JSON.stringify({
        url: "https://example.com/pricing",
        outputs: ["markdown", "structured"],
        extract: ["metadata", "tables"]
    })
});

const data = await res.json();

// Download the Markdown artifact from its signed URL
const markdownText = await fetch(data.outputs.markdown.url).then(r => r.text());

console.log(data.structured);
console.log(markdownText);

Wenn du EnConvert von Claude, Cursor oder einem anderen MCP-Client aus aufrufst, wird dieselbe Fähigkeit als das perceive_url-Tool bereitgestellt — siehe die MCP-Server-Seite.


Plan-Gating

V2-perceive-Operationen sind ein separater Zähler von V1-Konvertierungen. V1-Pläne enthalten kein perceive-Kontingent; du brauchst einen V2-inklusiven Plan.

Plan Perceive-Operationen / Monat Schema-Extraktion (LLM-Stufe)
Free 50 Nicht enthalten
Starter 850 Claude Haiku
Pro 8.500 Claude Haiku
Business 42.500 Claude Haiku
Enterprise Unbegrenzt Enthalten

Batch-Zugang und Größenlimits pro Batch, Basic-Auth-/Cookie-/Header- Unterstützung und proxy_url (Business+, sobald es kommt) sind durch den Plan gebunden. Aktuelle Zahlen stehen auf der Preisseite.


Fehlerantworten

Status Bedingung
400 Bad Request URL ist nicht http(s), trägt eingebettete Anmeldedaten oder löst zu einer privaten, Loopback- oder Link-local-Adresse auf (SSRF-Schutz).
400 Bad Request Ungültiges auth (fehlender username/password), cookies (kein Array, über 50 Einträge, fehlende Felder) oder headers (kein Objekt, über 20 Einträge, blockierter Name).
401 Unauthorized Fehlender oder ungültiger API-Schlüssel / JWT-Token.
402 Payment Required Perceive ist nicht in deinem aktuellen Plan, oder dein monatliches perceive-Kontingent ist erschöpft.
403 Forbidden /v2/perceive ist nicht in den erlaubten Endpunkten des API-Schlüssels.
403 Forbidden Batch in deinem Plan nicht verfügbar, oder Batch-Größe überschreitet das Limit deines Plans.
403 Forbidden respect_robots=true und die robots.txt der Seite verbietet die URL.
404 Not Found Unbekannte operation_id oder job_id, oder eine, die einem anderen Projekt gehört.
422 Unprocessable Entity Anfragevalidierung fehlgeschlagen (ungültiges Enum in outputs/extract, wait_timeout_ms außerhalb des Bereichs, Viewport außerhalb der Grenzen).
422 Unprocessable Entity proxy_url, geolocation oder action_chain wurde gesendet — reserviert für eine spätere Version.
500 Internal Server Error Der Render ist fehlgeschlagen. Die Meldung enthält die operation_id, die dem Support genannt werden kann.

Die vollständige Statuscode-Referenz steht in der Fehlercodes-Anleitung.


Limits

Limit Wert
URL-Länge 2.048 Zeichen
wait_timeout_ms 0–60.000 ms
js_code-Länge 20.000 Zeichen
Viewport-Breite 320–3.840 px
Viewport-Höhe 240–2.160 px
Cookies pro Anfrage 50
Benutzerdefinierte Header pro Anfrage 20
main_content-Extract 50.000 Zeichen
Batch-URLs pro Anfrage 1.000 (Schema-Deckel; das Batch-Limit deines Plans ist niedriger)
Inline-Batch-Schwelle 10 URLs (größere Batches laufen asynchron)
Ergebnis-Cache-TTL 1 Stunde
Ablauf signierter URL 15 Minuten
Monatliche perceive-Operationen Planabhängig (Free: 50)