> ## 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 Guide d'intégration de l'API de rendu de page

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

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

L'API de rendu de page WebExtrator est un service de rendu de page basé sur Chromium sans tête. Donnez une URL,
retourne le HTML complètement rendu (y compris le contenu injecté par JS), le texte brut, le titre de la page et l'URL finale.

Render est l'interface de base de WebExtrator. Si vous avez besoin de résultats d'extraction **structurés** (corps d'article,
prix des produits, ingrédients de recettes ...), veuillez utiliser
[`/webextrator/extract`](development_webextrator_extract) — il exécute une chaîne d'extraction typée complète sur la même base de rendu.

## Processus de demande

Pour utiliser la page de service WebExtrator, commencez par obtenir votre jeton API sur [le tableau de bord Ace Data Cloud](https://platform.acedata.cloud/console/applications), à conserver en réserve.

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

Si vous n'êtes pas encore connecté ou inscrit, vous serez automatiquement redirigé vers la page de connexion vous invitant à vous inscrire et à vous connecter, une fois terminé, vous serez automatiquement renvoyé à la page actuelle.

**Un jeton API suffit pour appeler tous les services de la plateforme, pas besoin de demander séparément pour chaque service.** La première demande vous donnera un quota gratuit, vous permettant de l'essayer gratuitement ; lorsque le quota est insuffisant, vous pouvez recharger le solde général dans le [tableau de bord](https://platform.acedata.cloud/console/coin).

> 📘 Documentation complète : [Page de service WebExtrator →](https://platform.acedata.cloud/service/webextrator)

## Authentification

Tous les interfaces WebExtrator utilisent l'authentification standard par Bearer Token :

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

## Paramètres de requête

| Champ               | Type      | Obligatoire | Par défaut                 | Description                                                                                                                      |
| ------------------- | --------- | :---------: | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `url`               | string    |      ✅      | —                          | L'URL de la page à rendre, doit être `http(s)://`.                                                                               |
| `user_agent`        | string    |      ❌      | Pool UA intégré tournant   | User-Agent personnalisé.                                                                                                         |
| `timeout`           | number    |      ❌      | `30`                       | Délai d'attente pour une navigation unique (**secondes**).                                                                       |
| `wait_until`        | enum      |      ❌      | `networkidle`              | Événement de chargement terminé : `load` / `domcontentloaded` / `networkidle` / `commit`.                                        |
| `delay`             | number    |      ❌      | `0`                        | **Temps d'attente supplémentaire en secondes** après le déclenchement de `wait_until` (pour le rendu secondaire des SPA).        |
| `wait_for_selector` | string    |      ❌      | —                          | Attendre l'apparition de ce sélecteur CSS, plus stable que `networkidle`.                                                        |
| `block_resources`   | string\[] |      ❌      | `["image","font","media"]` | Types de ressources à bloquer, options : `image` / `font` / `media` / `stylesheet` / `xhr` / `fetch`.                            |
| `headers`           | object    |      ❌      | —                          | En-têtes HTTP supplémentaires (par exemple `{"Accept-Language": "en-US"}`).                                                      |
| `cookies`           | array     |      ❌      | —                          | Cookies injectés avant la navigation, structure ci-dessous.                                                                      |
| `callback_url`      | string    |      ❌      | —                          | Adresse de rappel en mode asynchrone, la plateforme `POST` les résultats complets à cette adresse lorsque la tâche est terminée. |
| `bypass_cache`      | boolean   |      ❌      | `false`                    | Ignorer la lecture du cache Redis (mais écrira toujours le résultat dans le cache).                                              |
| `cache_ttl_seconds` | number    |      ❌      | `3600`                     | TTL de cache personnalisé pour cette écriture, passer `0` signifie ne pas mettre en cache cette réponse.                         |
| `async`             | boolean   |      ❌      | `false`                    | Si défini sur `true`, retourne immédiatement `task_id`, les résultats peuvent être récupérés via `callback_url` ou l'API Tasks.  |

> Les contrats de la plateforme utilisent uniformément **snake\_case**. Les services de rendu internes prennent en charge camelCase, mais tous les appels externes utilisent snake\_case.

### Structure des cookies

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

## Réponse synchrone

```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
  }
}
```

| Champ                | Type           | Description                                                                            |
| -------------------- | -------------- | -------------------------------------------------------------------------------------- |
| `data.kind`          | string         | Fixe `"render"`.                                                                       |
| `data.url`           | string         | L'URL que vous avez soumise.                                                           |
| `data.finalUrl`      | string         | L'URL finale après redirection.                                                        |
| `data.title`         | string         | `document.title` après rendu.                                                          |
| `data.status`        | number \| null | Code d'état HTTP de la navigation principale.                                          |
| `data.html`          | string         | HTML complet après rendu.                                                              |
| `data.text`          | string         | Instantané de `document.body.innerText` (pour un texte plus propre, utilisez Extract). |
| `data.userAgent`     | string         | UA réellement utilisé.                                                                 |
| `data.elapsedMs`     | number         | Temps pris uniquement pour le rendu du navigateur.                                     |
| `data.cached`        | boolean?       | `true` si le cache a été touché.                                                       |
| `data.cacheStoredAt` | number?        | Horodatage Unix en millisecondes de la première écriture de l'entrée de cache.         |

## Réponse asynchrone

Lorsque `async=true` (ou `callback_url` fourni), retourne immédiatement (HTTP 200) :

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

Les résultats seront poussés via `POST` à `callback_url` (si configuré), ou récupérés via
[`/webextrator/tasks`](development_webextrator_tasks).

### Structure de rappel

La plateforme `POST` un envelope **exactement identique** à celui du mode synchrone à `callback_url`,
`Content-Type: application/json`. Retourner n'importe quel `2xx` est considéré comme confirmé ; `5xx` sera
réessayé avec un backoff exponentiel pendant environ 5 minutes.

## Réponse d'erreur

| HTTP | `error.code`     | Signification                                                                                                 |
| ---- | ---------------- | ------------------------------------------------------------------------------------------------------------- |
| 400  | `bad_request`    | Le corps de la requête n'a pas passé la validation Zod (manque `url`, type incorrect, etc.).                  |
| 401  | `unauthorized`   | `Authorization: Bearer …` manquant ou invalide.                                                               |
| 402  | (x402)           | Solde de la plateforme insuffisant, retour de l'enveloppe de demande de paiement x402.                        |
| 408  | `timeout`        | Navigation dépassant le `timeout`.                                                                            |
| 429  | `queue_busy`     | La file d'attente de synchronisation est encombrée, veuillez réessayer ou utiliser `async=true`.              |
| 500  | `internal_error` | Exception non gérée côté serveur (plantage du navigateur, etc.), le Worker réessaie automatiquement une fois. |

Structure d'erreur :

```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: URL invalide" }
}
```

## Exemple

### 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);
```

### Asynchrone + 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"
  }'
```

Retourne immédiatement `{ "success": true, "task_id": "...", "trace_id": "...", "started_at": 1777717800.123 }` ; lorsque la tâche est terminée, la plateforme POST les résultats complets à votre `callback_url`.

### Forcer le contournement du 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
  }'
```

## Conseils et pièges

* **Il est très important de bien choisir `wait_until`.** `networkidle` est le plus stable mais le plus lent ; `domcontentloaded` est rapide mais peut manquer du contenu injecté de manière asynchrone ; `load` convient aux pages statiques traditionnelles.
* **La clé de cache ignore `async`.** Les requêtes synchrones et asynchrones pour la même URL frappent la même entrée de cache, le changement aléatoire ne provoquera pas d'échec.
* **La clé de cache ignore `bypass_cache` et `cache_ttl_seconds`.** Ces deux éléments sont des interrupteurs d'opération, n'affectent pas le contenu de la réponse.
* **Les `cookies` et `headers` seront mis en cache par groupe.** Personnaliser ces deux éléments fera échouer la première combinaison identique.
* **Les SPA lourdes dépassent souvent les 30 secondes par défaut.** Il est conseillé de définir `timeout: 60`, `wait_until: "domcontentloaded"`, `delay: 4`, puis d'utiliser `wait_for_selector` pour attendre les éléments réellement concernés.
* **`block_resources` est le chemin le plus rapide pour réduire la latence.** Par défaut, les images / polices / médias sont déjà bloqués ; si vous extrayez sans dépendre de la mise en page CSS, ajouter `stylesheet` peut encore accélérer.
