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

API рендеринга веб-страниц WebExtrator — это сервис рендеринга веб-страниц на основе безголового 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 задач. |

> Платформенные контракты используют **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         | Снимок `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` отправляет **абсолютно такой же** envelope в `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` может сделать это еще быстрее.
