Perceive

POST /v2/perceive renderizza un URL una sola volta in un browser reale e ti restituisce ogni output che richiedi da quel singolo render: Markdown, HTML ripulito o grezzo, uno screenshot, un PDF, l'inventario di link e immagini e dati strutturati (metadati della pagina, JSON-LD, intestazioni, tabelle). Sostituisce una serie di chiamate separate — url-to-markdown, url-to-screenshot, url-to-pdf, oltre al tuo scraping personalizzato — con una sola richiesta.

Ecco la chiamata utile più piccola. Invia un URL e ricevi Markdown pulito e i metadati strutturati della pagina:

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"]
  }'

La risposta contiene un URL di download pre-firmato per il file Markdown e il blocco strutturato 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": []
}

Da segnalare subito. /v2/perceive è un endpoint V2 con un proprio contatore di quota. I piani di conversione V1 non includono alcuna operazione di perceive V2 — ti serve un piano che includa V2 per chiamarlo. Vedi la pagina dei prezzi per le quote per ciascun tier.


Endpoints

Method Path Purpose
POST /v2/perceive Percepisce un singolo URL e restituisce gli output che hai richiesto.
GET /v2/perceive/{operation_id} Recupera di nuovo un'operazione passata con URL di download firmati ex novo.
POST /v2/perceive/batch Percepisce fino a 1.000 URL che condividono lo stesso set di opzioni.
GET /v2/perceive/batch/{job_id} Interroga lo stato e i risultati per ciascun URL di un batch.

Content-Type: application/json su ogni POST.


Authentication

Autentica con una chiave privata nell'header X-API-Key per le chiamate server-to-server. Questo è il percorso usato dagli esempi qui sotto.

X-API-Key: sk_live_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, è nella guida all'autenticazione.

Ogni chiave API porta con sé un allowlist di endpoint consentiti. Se /v2/perceive non è nella lista della chiave, la richiesta viene rifiutata con 403.


How perceive works

Una richiesta innesca un render del browser tramite un singleton Chrome headless condiviso, poi materializza ogni output da quel render. Non paghi mai due volte per la stessa pagina in una singola chiamata.

  1. Render. La pagina viene caricata in Chrome headless. I banner dei cookie vengono chiusi, la pagina viene scrollata per innescare i contenuti caricati in modalità lazy, gli header sticky vengono gestiti e alle immagini viene dato il tempo di caricarsi — la stessa pipeline di cattura che alimenta l'endpoint url-to-pdf.
  2. Materialise. Dal DOM renderizzato, perceive costruisce tutto ciò che hai elencato in outputs: Markdown, HTML ripulito/grezzo, link, immagini, uno screenshot, un PDF.
  3. Extract. Se hai richiesto l'output structured, perceive esegue un passaggio euristico per i metadati della pagina, JSON-LD, intestazioni e tabelle. Se invii anche uno schema e il tuo piano include il tier LLM, un modello Anthropic Claude Haiku riempie lo schema quando il passaggio euristico risulta insufficiente.
  4. Score. Un punteggio di qualità del render (0.0–1.0) segnala le pagine che sembrano bloccate da protezioni anti-bot o nascoste dietro un login wall, così puoi distinguere un render reale da una pagina di challenge.

Gli output binari e di testo (Markdown, HTML, screenshot, PDF, il JSON di link e immagini) vengono caricati nello storage e restituiti come URL pre-firmati che scadono dopo 15 minuti. Il blocco structured viene restituito inline nel JSON. Recupera di nuovo qualsiasi operazione con GET /v2/perceive/{operation_id} per ottenere un nuovo set di URL firmati.


Request parameters

Core

Parameter Type Default Description
url string La pagina da percepire. Deve iniziare con http:// o https://. Massimo 2.048 caratteri. Obbligatorio.
outputs string[] ["markdown", "structured"] Quali output produrre. Vedi Outputs.
extract string[] [] Quali campi strutturati estrarre quando structured è in outputs. Vedi Structured extraction.
schema object null Uno schema JSON che descrive i campi che vuoi estrarre. Attiva il tier di estrazione LLM nei piani che lo includono.
cache_mode string "enabled" enabled, bypass, o refresh. Vedi Caching.

Outputs

outputs accetta qualsiasi combinazione di questi nomi:

Output Returned as What you get
markdown signed URL Markdown pulito dal contenuto principale, con link e immagini risolti in URL assoluti.
markdown_fit signed URL Markdown "Fit" — una variante ridotta e più densa, ottimizzata per le finestre di contesto degli LLM.
html_cleaned signed URL L'HTML renderizzato con script, stili e boilerplate rimossi.
html_raw signed URL L'HTML renderizzato completo, esattamente come prodotto dal browser.
screenshot signed URL Un PNG del viewport alla dimensione del viewport richiesta (o di default).
screenshot_full_page signed URL Un PNG dell'intera pagina che cattura tutta l'altezza dello scroll.
pdf signed URL Un PDF della pagina. Accetta l'intera superficie di pdf_options (vedi sotto).
links signed URL Un array JSON di ogni link trovato, con URL assoluti e testo dell'anchor.
images signed URL Un array JSON di ogni immagine, con src assoluto e testo alt.
structured inline JSON Dati strutturati estratti dalla pagina (il campo di risposta structured).

Rendering and waiting

Parameter Type Default Description
viewport object 1920 x 1080 {"width": <int>, "height": <int>}. Larghezza 320–3840, altezza 240–2160.
mobile boolean false Renderizza con un viewport mobile (390 x 844) a meno che viewport non sia impostato esplicitamente.
wait_for string null Attende dopo la navigazione un selettore CSS (".price" o "css:.price") o un'espressione JS ("js:window.dataReady === true").
wait_timeout_ms integer 30000 Per quanto tempo wait_for può attendere, in millisecondi. 0–60.000. Un timeout degrada a un warning; la pagina viene catturata così com'è.
js_code string null JavaScript da eseguire sulla pagina dopo la navigazione. Massimo 20.000 caratteri. Un errore diventa un warning, non un fallimento.
block_resources string[] [] Tipi di risorse da interrompere prima che vengano caricate. Uno qualsiasi tra image, media, font, stylesheet, script, xhr, fetch, websocket, manifest, other. Utile per render più veloci e di solo testo.
respect_robots boolean false Quando è true, un URL non consentito dal robots.txt del sito viene rifiutato con 403.
pdf_options object null Formato pagina, margini, intestazioni, piè di pagina, scala e orientamento per l'output pdf. Lo stesso oggetto di url-to-pdf. Senza pdf_options, perceive produce un'unica pagina continua, identica byte per byte a url-to-pdf V1.

Authenticated and custom requests

Parameter Type Default Description
auth object null HTTP Basic Auth per la pagina di destinazione: {"username": "...", "password": "..."}.
cookies array null Cookie da iniettare prima della navigazione. Massimo 50. Ognuno necessita di name, value, e o domain o url.
headers object null Header di richiesta personalizzati. Massimo 20. Nomi bloccati: host, content-length, transfer-encoding, connection, upgrade, te, trailer.
Riservati, non ancora attivi. proxy_url (Business+), geolocation, e action_chain sono accettati dallo schema della richiesta ma oggi restituiscono 422. Arriveranno in una release successiva; inviarli ora ti dice esattamente quale manopola non è pronta invece di ignorarla silenziosamente.

Structured extraction

Quando structured è in outputs, la lista extract controlla quali campi perceive estrae. Non chiedere nulla e il default sarà metadata e structured_data.

extract value Field in structured Status
metadata metadata Attivo
structured_data structured_data (JSON-LD) Attivo
headings headings Attivo
tables tables Attivo
main_content main_content (testo, limitato a 50.000 caratteri) Attivo
all si espande in ogni campo attivo qui sopra Attivo
prices Non ancora — restituisce un warning, omesso
contacts Non ancora — restituisce un warning, omesso
technologies Non ancora — restituisce un warning, omesso

Per essere chiari: prices, contacts, e technologies sono nomi riservati. Richiederne uno oggi non genera errore — finisce nell'array warnings e viene scartato da structured.

Schema-driven extraction

Invia uno schema per estrarre campi specifici in structured.extracted:

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

Il tier di estrazione LLM (Anthropic Claude Haiku) riempie lo schema, e si attiva solo quando valgono tutte queste condizioni: hai inviato uno schema, il tuo piano include il tier LLM (Starter e superiori), la pagina non è stata segnata come bloccata, e il passaggio euristico ha lasciato vuoti i campi dello schema. Quando viene eseguito, extraction_tier è "llm", e tokens e cost_cents riportano quanto è costata quell'estrazione; altrimenti extraction_tier è "heuristic" ed entrambi sono zero.

Nota. L'estrazione da schema ha un tetto rigido per proteggere il tuo conto: una singola estrazione ha un limite per richiesta, e la spesa giornaliera per progetto ha un limite per piano. Se viene raggiunto un limite, perceive restituisce il risultato euristico con una nota in warnings invece di spendere troppo. Su un piano senza il tier LLM, ottieni solo dati structured euristici.


Response

Sia POST /v2/perceive che GET /v2/perceive/{operation_id} restituiscono lo stesso oggetto.

Field Type Description
operation_id string ID opaco (per_...). Usalo con l'endpoint GET e citalo al supporto.
status string queued, processing, completed, o failed.
url string L'URL che hai inviato.
url_final string L'URL dopo i redirect.
content_hash string SHA-256 della pagina renderizzata. Pilota la cache di 1 ora.
render_quality number 0.0–1.0. I punteggi bassi segnalano challenge anti-bot o login wall.
cache_hit boolean true quando il risultato proviene dalla cache invece che da un render nuovo.
outputs object Mappa del nome dell'output verso {url, object_key, size_bytes, content_type, expires_in}. Gli URL firmati scadono in 900 secondi.
structured object Dati strutturati inline, presenti quando structured è stato richiesto.
extraction_tier string heuristic, css, o llm.
tokens object {input, output} token LLM usati. Zero a meno che il tier LLM non sia stato eseguito.
cost_cents number Costo LLM in centesimi per questa operazione. Zero a meno che il tier LLM non sia stato eseguito.
duration_ms integer Tempo di render end-to-end.
error string Impostato solo quando status è failed.
warnings string[] Note non fatali: un timeout di wait_for, un extract saltato, un flag di pagina bloccata.

Retrieve an operation

Gli URL firmati scadono dopo 15 minuti. Per scaricare un output più tardi, recupera di nuovo l'operazione — perceive ri-firma ogni URL dalle object key memorizzate. Non avviene alcun nuovo render, quindi questo non consuma quota.

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

Un ID di operazione sconosciuto, o uno che appartiene a un altro progetto, restituisce 404 — l'esistenza non viene mai rivelata tra progetti.


Batch perception

POST /v2/perceive/batch percepisce una lista di URL che condividono uno stesso blocco options. Ogni URL viene renderizzato attraverso la stessa pipeline di una chiamata singola e produce la propria riga di operazione.

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"
  }'

I batch di 10 URL o meno vengono eseguiti inline e rispondono 200 con ogni risultato popolato. I batch più grandi rispondono 202 con un job_id; gli URL vengono drenati uno alla volta e tu interroghi per i risultati:

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

La risposta del batch riporta l'avanzamento aggregato e contiene un risultato perceive completo per ciascun URL una volta renderizzato:

{
    "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 è queued, processing, completed, failed, o partial (alcuni URL sono riusciti, altri sono falliti). Imposta output_mode su zip per raggruppare ogni artefatto in un unico ZIP, restituito sotto il campo zip una volta che il batch è terminato. L'accesso ai batch e la dimensione massima del batch sono limitati dal piano; vedi la pagina dei prezzi.


Caching

cache_mode controlla come perceive tratta la sua cache di risultati di 1 ora, indicizzata per il tuo progetto, l'URL, e le opzioni di richiesta che influenzano il render.

cache_mode Behaviour
enabled (default) Restituisce un risultato dalla cache quando una richiesta identica è stata renderizzata nell'ultima ora. cache_hit è true, cost_cents è 0.
bypass Salta la cache e renderizza ex novo.
refresh Renderizza ex novo e sostituisce la voce in cache.

Da segnalare: un cache hit conta comunque come una operazione di perceive sulla tua quota mensile. La quota misura le operazioni, non i render del browser — la cache ti fa risparmiare tempo di render, non quota.


Code examples

curl — Markdown only

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 structured data

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 — Full outputs 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);

Se chiami EnConvert da Claude, Cursor, o un altro client MCP, la stessa capacità è esposta come tool perceive_url — vedi la pagina del server MCP.


Plan gating

Le operazioni di perceive V2 sono un contatore separato dalle conversioni V1. I piani V1 non includono alcuna quota di perceive; ti serve un piano che includa V2.

Plan Perceive operations / month Schema extraction (LLM tier)
Free 50 Non incluso
Starter 850 Claude Haiku
Pro 8,500 Claude Haiku
Business 42,500 Claude Haiku
Enterprise Unlimited Incluso

L'accesso ai batch e i limiti di dimensione per batch, il supporto a basic-auth/cookie/header, e proxy_url (Business+, quando verrà rilasciato) sono limitati dal piano. I numeri attuali si trovano su la pagina dei prezzi.


Error responses

Status Condition
400 Bad Request L'URL non è http(s), contiene credenziali incorporate, o risolve a un indirizzo privato, loopback, o link-local (protezione SSRF).
400 Bad Request auth non valido (manca username/password), cookies (non è un array, oltre 50 voci, campi mancanti), o headers (non è un oggetto, oltre 20 voci, nome bloccato).
401 Unauthorized Chiave API / token JWT mancante o non valido.
402 Payment Required Perceive non è nel tuo piano attuale, o la tua quota mensile di perceive è esaurita.
403 Forbidden /v2/perceive non è negli endpoint consentiti della chiave API.
403 Forbidden Batch non disponibile nel tuo piano, o la dimensione del batch supera il limite del tuo piano.
403 Forbidden respect_robots=true e il robots.txt del sito non consente l'URL.
404 Not Found operation_id o job_id sconosciuto, o uno appartenente a un altro progetto.
422 Unprocessable Entity La validazione della richiesta è fallita (enum errato in outputs/extract, wait_timeout_ms fuori range, viewport fuori dai limiti).
422 Unprocessable Entity proxy_url, geolocation, o action_chain è stato inviato — riservato a una release successiva.
500 Internal Server Error Il render è fallito. Il messaggio include l'operation_id da citare al supporto.

Il riferimento completo dei codici di stato è nella guida ai codici di errore.


Limits

Limit Value
Lunghezza URL 2.048 caratteri
wait_timeout_ms 0–60.000 ms
Lunghezza js_code 20.000 caratteri
Larghezza viewport 320–3.840 px
Altezza viewport 240–2.160 px
Cookie per richiesta 50
Header personalizzati per richiesta 20
Extract main_content 50.000 caratteri
URL per batch per richiesta 1.000 (limite schema; il limite di batch del tuo piano è inferiore)
Soglia batch inline 10 URL (i batch più grandi vengono eseguiti in modo asincrono)
TTL cache risultati 1 ora
Scadenza URL firmato 15 minuti
Operazioni di perceive mensili Dipendente dal piano (Free: 50)