> ## 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 API інтеграційний посібник для рендерингу веб-сторінок

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

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

WebExtrator API для рендерингу веб-сторінок — це сервіс рендерингу веб-сторінок на основі безголового Chromium. Надсилаючи URL, ви отримуєте повністю відрендерений HTML (включаючи вміст, інжектований через JS), чистий текст, заголовок сторінки та остаточний URL.

Render є найнижчим рівнем інтерфейсу WebExtrator. Якщо вам потрібні **структуровані** результати витягування (основний текст статті, ціни на товари, інгредієнти рецептів тощо), будь ласка, використовуйте
[`/webextrator/extract`](development_webextrator_extract) — він працює на тій же основі рендерингу, але виконує повний набір типізованих витягувальних процесів.

## Процес подачі заявки

Щоб використовувати сервіс WebExtrator, спочатку перейдіть до [консолі Ace Data Cloud](https://platform.acedata.cloud/console/applications) та отримайте свій API Token для резервного копіювання.

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

Якщо ви ще не увійшли в систему або не зареєстровані, вас автоматично перенаправлять на сторінку входу, щоб запросити реєстрацію та вхід. Після завершення ви будете автоматично повернені на поточну сторінку.

**Один API Token дозволяє викликати всі сервіси платформи, не потрібно окремо подавати заявку на кожен сервіс.** Перший запит на отримання токена надає безкоштовний ліміт, щоб ви могли безкоштовно протестувати; якщо ліміт вичерпано, ви можете поповнити загальний баланс в [консолі](https://platform.acedata.cloud/console/coin).

> 📘 Повна документація: [Сервіс WebExtrator →](https://platform.acedata.cloud/service/webextrator)

## Аутентифікація

Всі інтерфейси WebExtrator використовують стандартну аутентифікацію Bearer Token:

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

## Параметри запиту

| Поле                | Тип       | Обов'язкове | За замовчуванням           | Опис                                                                                                                            |
| ------------------- | --------- | :---------: | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `url`               | string    |      ✅      | —                          | URL сторінки для рендерингу, повинен бути `http(s)://`.                                                                         |
| `user_agent`        | string    |      ❌      | Вбудований пул UA          | Користувацький User-Agent.                                                                                                      |
| `timeout`           | number    |      ❌      | `30`                       | Час очікування для одного навігаційного запиту (**секунди**).                                                                   |
| `wait_until`        | enum      |      ❌      | `networkidle`              | Подія завершення завантаження: `load` / `domcontentloaded` / `networkidle` / `commit`.                                          |
| `delay`             | number    |      ❌      | `0`                        | **Додаткова кількість секунд очікування** після спрацьовування `wait_until` (для повторного рендерингу SPA).                    |
| `wait_for_selector` | string    |      ❌      | —                          | Очікування появи цього CSS селектора, більш стабільно, ніж `networkidle`.                                                       |
| `block_resources`   | string\[] |      ❌      | `["image","font","media"]` | Типи ресурсів, які потрібно заблокувати, необов'язково: `image` / `font` / `media` / `stylesheet` / `xhr` / `fetch`.            |
| `headers`           | object    |      ❌      | —                          | Додаткові HTTP заголовки запиту (наприклад, `{"Accept-Language": "en-US"}`).                                                    |
| `cookies`           | array     |      ❌      | —                          | Cookie, які потрібно ввести перед навігацією, структура наведена нижче.                                                         |
| `callback_url`      | string    |      ❌      | —                          | Адреса зворотного виклику в асинхронному режимі, платформа надішле повний результат на цю адресу, коли завдання буде завершено. |
| `bypass_cache`      | boolean   |      ❌      | `false`                    | Пропустити читання кешу Redis (але все ще запише результати цього разу в кеш).                                                  |
| `cache_ttl_seconds` | number    |      ❌      | `3600`                     | Налаштування TTL кешу для цього запису, передайте `0`, щоб не кешувати цю відповідь.                                            |
| `async`             | boolean   |      ❌      | `false`                    | Встановіть `true`, щоб негайно повернути `task_id`, результати можна отримати через `callback_url` або API Tasks.               |

> Платформені контракти використовують **snake\_case**. Внутрішні сервіси рендерингу підтримують camelCase, але зовнішні виклики завжди використовують snake\_case.

### Структура Cookie

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

## Синхронна відповідь

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

| Поле                 | Тип            | Опис                                                                              |
| -------------------- | -------------- | --------------------------------------------------------------------------------- |
| `data.kind`          | string         | Фіксоване `"render"`.                                                             |
| `data.url`           | string         | URL, який ви подали.                                                              |
| `data.finalUrl`      | string         | Остаточний URL після перенаправлення.                                             |
| `data.title`         | string         | `document.title` після рендерингу.                                                |
| `data.status`        | number \| null | HTTP статус код основної навігації.                                               |
| `data.html`          | string         | Повний HTML після рендерингу.                                                     |
| `data.text`          | string         | Сnapshot `document.body.innerText` (для чистішого тексту використовуйте Extract). |
| `data.userAgent`     | string         | Фактично використаний UA.                                                         |
| `data.elapsedMs`     | number         | Час, витрачений лише на рендеринг браузера.                                       |
| `data.cached`        | boolean?       | Якщо кеш було використано, то `true`.                                             |
| `data.cacheStoredAt` | number?        | Unix мілісекундний таймштамп, коли кешовий запис було вперше записано.            |

## Асинхронна відповідь

`async=true` (або надано `callback_url`) негайно повертає (HTTP 200):

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

Результати будуть надіслані через `POST` на `callback_url` (якщо він налаштований), або через
[`/webextrator/tasks`](development_webextrator_tasks) активним запитом.

### Структура зворотного виклику

Платформа `POST` надсилає **повністю таку ж** оболонку, як і в синхронному режимі, на `callback_url`,
`Content-Type: application/json`. Повернення будь-якого `2xx` вважається підтвердженим; `5xx` буде повторюватися з експоненційною затримкою протягом приблизно 5 хвилин.

## Відповідь про помилку

| HTTP | `error.code`     | Значення                                                                                       |
| ---- | ---------------- | ---------------------------------------------------------------------------------------------- |
| 400  | `bad_request`    | Тіло запиту не пройшло перевірку Zod (не вистачає `url`, неправильний тип …).                  |
| 401  | `unauthorized`   | Відсутній або недійсний `Authorization: Bearer …`.                                             |
| 402  | (x402)           | Недостатньо коштів на платформі, повертається x402 вимога на оплату.                           |
| 408  | `timeout`        | Навігація перевищила `timeout`.                                                                |
| 429  | `queue_busy`     | Черга синхронізації переповнена, будь ласка, спробуйте ще раз або використовуйте `async=true`. |
| 500  | `internal_error` | Внутрішня помилка сервера (вимкнення браузера тощо), Worker автоматично повторює спробу.       |

Структура помилки:

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

## Приклад

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

### Асинхронно + зворотний виклик

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

Негайно повертає `{ "success": true, "task_id": "...", "trace_id": "...", "started_at": 1777717800.123 }`;
коли завдання завершиться, платформа надішле повний результат на ваш `callback_url`.

### Примусове обходження кешу

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

## Поради та підводні камені

* **Важливо правильно вибрати `wait_until`.** `networkidle` найстабільніший, але найповільніший; `domcontentloaded` швидкий, але може пропустити асинхронно завантажений контент; `load` підходить для традиційних статичних сторінок.
* **Кеш-ключ ігнорує `async`.** Синхронні та асинхронні запити до одного й того ж URL потрапляють в один і той же кеш-елемент, випадкове перемикання не призведе до збою.
* **Кеш-ключ ігнорує `bypass_cache` та `cache_ttl_seconds`.** Ці два є перемикачами, не впливають на вміст відповіді.
* **`cookies` та `headers` кешуються окремо.** Налаштування цих двох призведе до невдачі при першому попаданні однакових комбінацій.
* **Важкі SPA часто перевищують стандартні 30 секунд.** Рекомендується `timeout: 60`, `wait_until: "domcontentloaded"`, `delay: 4`, а також використовувати `wait_for_selector` для очікування дійсно важливих елементів.
* **`block_resources` є найшвидшим шляхом для зменшення затримки.** За замовчуванням вже заблоковані зображення / шрифти / медіа; якщо ви витягуєте, не покладаючись на CSS-розмітку, додавання `stylesheet` може ще більше прискорити процес.
