> ## Documentation Index
> Fetch the complete documentation index at: https://docs.acedata.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# WebExtrator Guida all'integrazione dell'API di rendering delle pagine web

> WebExtrator Web Render & Extract API guide - Ace Data Cloud

`POST https://api.acedata.cloud/webextrator/render`

L'API di rendering delle pagine web WebExtrator è un servizio di rendering basato su Chromium senza testa. Fornisci un URL,
restituisce l'HTML completamente renderizzato (inclusi i contenuti iniettati da JS), testo semplice, titolo della pagina e URL finale.

Render è l'interfaccia di base di WebExtrator. Se hai bisogno di risultati di estrazione **strutturati** (testo dell'articolo,
prezzi dei prodotti, ingredienti delle ricette ...), utilizza
[`/webextrator/extract`](development_webextrator_extract) —— che esegue un'intera pipeline di estrazione tipizzata sulla stessa base di rendering.

## Processo di richiesta

Per utilizzare la pagina del servizio WebExtrator, prima vai al [Pannello di controllo di Ace Data Cloud](https://platform.acedata.cloud/console/applications) per ottenere il tuo API Token, da conservare per uso futuro.

![](https://cdn.acedata.cloud/5hmkdg.jpg)

Se non hai ancora effettuato il login o registrato, verrai automaticamente reindirizzato alla pagina di login che ti invita a registrarti e accedere, una volta completato verrai automaticamente riportato alla pagina corrente.

**Un API Token è sufficiente per accedere a tutti i servizi della piattaforma, non è necessario richiederne uno separato per ogni servizio.** La prima richiesta riceverà un credito gratuito, per un'esperienza gratuita; quando il credito è insufficiente, puoi ricaricare il saldo generale nel [pannello di controllo](https://platform.acedata.cloud/console/coin).

> 📘 Documentazione completa: [Pagina del servizio WebExtrator →](https://platform.acedata.cloud/service/webextrator)

## Autenticazione

Tutte le interfacce WebExtrator utilizzano l'autenticazione standard Bearer Token:

```
Authorization: Bearer YOUR_API_KEY
Content-Type:  application/json
```

## Parametri di richiesta

| Campo               | Tipo      | Obbligatorio | Predefinito                | Descrizione                                                                                                                          |
| ------------------- | --------- | :----------: | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `url`               | string    |       ✅      | —                          | URL della pagina da renderizzare, deve essere `http(s)://`.                                                                          |
| `user_agent`        | string    |       ❌      | Pool UA integrato rotante  | User-Agent personalizzato.                                                                                                           |
| `timeout`           | number    |       ❌      | `30`                       | Timeout per navigazione singola (**secondi**).                                                                                       |
| `wait_until`        | enum      |       ❌      | `networkidle`              | Evento di completamento del caricamento: `load` / `domcontentloaded` / `networkidle` / `commit`.                                     |
| `delay`             | number    |       ❌      | `0`                        | **Secondi di attesa aggiuntivi** dopo il trigger di `wait_until` (per il secondo rendering di SPA).                                  |
| `wait_for_selector` | string    |       ❌      | —                          | Attendere che questo selettore CSS appaia, più stabile di `networkidle`.                                                             |
| `block_resources`   | string\[] |       ❌      | `["image","font","media"]` | Tipi di risorse da bloccare, opzioni: `image` / `font` / `media` / `stylesheet` / `xhr` / `fetch`.                                   |
| `headers`           | object    |       ❌      | —                          | Intestazioni HTTP aggiuntive (es. `{"Accept-Language": "en-US"}`).                                                                   |
| `cookies`           | array     |       ❌      | —                          | Cookie iniettati prima della navigazione, struttura come sotto.                                                                      |
| `callback_url`      | string    |       ❌      | —                          | Indirizzo di callback in modalità asincrona, la piattaforma `POST` i risultati completi a questo indirizzo al termine del compito.   |
| `bypass_cache`      | boolean   |       ❌      | `false`                    | Salta la lettura della cache Redis (ma scriverà comunque il risultato nella cache).                                                  |
| `cache_ttl_seconds` | number    |       ❌      | `3600`                     | TTL della cache personalizzato per questa scrittura, invia `0` per non memorizzare questa risposta.                                  |
| `async`             | boolean   |       ❌      | `false`                    | Imposta su `true` per restituire immediatamente `task_id`, i risultati possono essere recuperati tramite `callback_url` o Tasks API. |

> Il contratto della piattaforma utilizza uniformemente **snake\_case**. I servizi di rendering interni supportano camelCase, ma le chiamate esterne utilizzano sempre snake\_case.

### Struttura dei Cookie

```json theme={null}
{
  "name":      "string",
  "value":     "string",
  "domain":    "string",
  "path":      "/",
  "expires":   1735689600,
  "httpOnly":  false,
  "secure":    true,
  "sameSite":  "Lax"
}
```

## Risposta sincrona

```json theme={null}
{
  "success": true,
  "task_id": "550e8400-e29b-41d4-a716-446655440000",
  "trace_id": "550e8400-e29b-41d4-a716-446655440001",
  "started_at": 1777717800.123,
  "finished_at": 1777717801.234,
  "elapsed": 1.111,
  "data": {
    "kind": "render",
    "url": "https://example.com",
    "finalUrl": "https://example.com/",
    "title": "Example Domain",
    "status": 200,
    "html": "<!DOCTYPE html><html>...</html>",
    "text": "Example Domain\nThis domain is for use in illustrative examples...",
    "userAgent": "Mozilla/5.0 ...",
    "elapsedMs": 1108
  }
}
```

| Campo                | Tipo           | Descrizione                                                                        |
| -------------------- | -------------- | ---------------------------------------------------------------------------------- |
| `data.kind`          | string         | Fisso `"render"`.                                                                  |
| `data.url`           | string         | L'URL che hai inviato.                                                             |
| `data.finalUrl`      | string         | URL finale dopo il reindirizzamento.                                               |
| `data.title`         | string         | `document.title` renderizzato.                                                     |
| `data.status`        | number \| null | Codice di stato HTTP della navigazione principale.                                 |
| `data.html`          | string         | HTML completo dopo il rendering.                                                   |
| `data.text`          | string         | Snapshot di `document.body.innerText` (per un testo più pulito, utilizza Extract). |
| `data.userAgent`     | string         | UA effettivamente utilizzato.                                                      |
| `data.elapsedMs`     | number         | Tempo impiegato solo per il rendering del browser.                                 |
| `data.cached`        | boolean?       | `true` se è stata colpita la cache.                                                |
| `data.cacheStoredAt` | number?        | Timestamp Unix in millisecondi della prima scrittura dell'elemento della cache.    |

## Risposta asincrona

Quando `async=true` (o fornisci `callback_url`) restituisce immediatamente (HTTP 200):

```json theme={null}
{
  "success": true,
  "task_id": "550e8400-...",
  "trace_id": "6ba7b810-...",
  "started_at": 1777717800.123
}
```

I risultati verranno inviati tramite `POST` a `callback_url` (se configurato), oppure tramite
[`/webextrator/tasks`](development_webextrator_tasks) per interrogare attivamente.

### Struttura del callback

La piattaforma `POST` invia un envelope **identico** a quello della modalità sincrona a `callback_url`,
`Content-Type: application/json`. Restituire qualsiasi `2xx` è considerato confermato; `5xx` verrà riprovato con backoff esponenziale per circa 5 minuti.

## Risposta di errore

| HTTP | `error.code`     | Significato                                                                                           |
| ---- | ---------------- | ----------------------------------------------------------------------------------------------------- |
| 400  | `bad_request`    | Il corpo della richiesta non ha superato la validazione Zod (manca `url`, tipo errato …).             |
| 401  | `unauthorized`   | Mancanza o invalidità di `Authorization: Bearer …`.                                                   |
| 402  | (x402)           | Saldo della piattaforma insufficiente, restituisce x402 richiesta di pagamento envelope.              |
| 408  | `timeout`        | Navigazione oltre il `timeout`.                                                                       |
| 429  | `queue_busy`     | La coda di sincronizzazione è affollata, riprova o usa `async=true`.                                  |
| 500  | `internal_error` | Eccezione non gestita dal server (crash del browser, ecc.), Worker riprova automaticamente una volta. |

Struttura dell'errore:

```json theme={null}
{
  "success": false,
  "task_id": "...",
  "trace_id": "...",
  "started_at": 1777717800.123,
  "finished_at": 1777717800.135,
  "elapsed": 0.012,
  "error": { "code": "bad_request", "message": "url: Invalid url" }
}
```

## Esempio

### cURL

```bash theme={null}
curl -X POST https://api.acedata.cloud/webextrator/render \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "wait_until": "networkidle",
    "block_resources": ["image", "media", "font"]
  }'
```

### Python (requests)

```python theme={null}
import os, requests

API_KEY = os.environ["ACEDATA_API_KEY"]

resp = requests.post(
    "https://api.acedata.cloud/webextrator/render",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "url": "https://example.com",
        "wait_until": "networkidle",
        "block_resources": ["image", "media", "font"],
    },
    timeout=60,
)
resp.raise_for_status()
data = resp.json()["data"]
print(data["title"], data["status"], len(data["html"]))
```

### Node.js (fetch)

```js theme={null}
const apiKey = process.env.ACEDATA_API_KEY;

const res = await fetch('https://api.acedata.cloud/webextrator/render', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com',
    wait_until: 'networkidle',
    block_resources: ['image', 'media', 'font'],
  }),
});
const { data } = await res.json();
console.log(data.title, data.status, data.html.length);
```

### Asincrono + Callback

```bash theme={null}
curl -X POST https://api.acedata.cloud/webextrator/render \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "async": true,
    "callback_url": "https://your-app.example.com/hooks/webextrator"
  }'
```

Restituisce immediatamente `{ "success": true, "task_id": "...", "trace_id": "...", "started_at": 1777717800.123 }`;
Quando il compito è completato, la piattaforma invierà un POST con il risultato completo al tuo `callback_url`.

### Forzare il bypass della cache

```bash theme={null}
curl -X POST https://api.acedata.cloud/webextrator/render \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "bypass_cache": true
  }'
```

## Suggerimenti e problemi

* **È importante scegliere correttamente `wait_until`.** `networkidle` è il più stabile ma il più lento; `domcontentloaded`
  è veloce ma potrebbe perdere contenuti iniettati in modo asincrono; `load` è adatto per pagine statiche tradizionali.
* **La chiave della cache ignora `async`.** Le richieste sincrone e asincrone per lo stesso URL colpiscono la stessa voce di cache,
  passare liberamente non causerà errori.
* **La chiave della cache ignora `bypass_cache` e `cache_ttl_seconds`.** Questi due sono interruttori operativi,
  non influenzano il contenuto della risposta.
* **I `cookies` e gli `headers` verranno memorizzati in cache separatamente.** Personalizzare questi due farà sì che la prima combinazione identica fallisca.
* **Le SPA pesanti superano spesso i 30 secondi predefiniti.** Si consiglia `timeout: 60`, `wait_until: "domcontentloaded"`, `delay: 4`, insieme a `wait_for_selector` per attendere gli elementi di reale interesse.
* **`block_resources` è il modo più veloce per ridurre la latenza.** Per impostazione predefinita, sono già bloccati immagini / font / media;
  se l'estrazione non dipende dal layout CSS, aggiungere `stylesheet` può rendere tutto ancora più veloce.
