> ## 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 inteligentny interfejs API do ekstrakcji

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

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

WebExtrator inteligentny interfejs API przekształca URL w **typizowane wyniki strukturalne** — artykuły, produkty, przepisy, filmy, dyskusje, oferty pracy itp., a także dostarcza oczyszczony Markdown i czysty tekst. Gdy chcesz uzyskać "czyste dane strukturalne" zamiast surowego HTML, to jest interfejs, którego należy użyć.

Na dole znajduje się trójwarstwowa linia produkcyjna:

1. **mapper JSON-LD schema.org** — deterministyczny, zerowy koszt LLM. Obejmuje Wikipedia / BestBuy / AllRecipes / YouTube / większość wiadomości / większość stron produktów.
2. **typizowane LLM ekstrakcje** — uruchamiane tylko wtedy, gdy schema.org nie jest trafione. Wybierz schemat według typu strony, ścisła walidacja Zod.
3. **Readability + Markdown jako zabezpieczenie** — zawsze działa, uzupełniając górne pola, które nie zostały wypełnione przez dwie pierwsze warstwy.

Powtarzające się żądania URL będą przechwytywane przez pamięć podręczną wyników Redis, \<1 ms zwrotu.

## Proces aplikacji

Aby korzystać z usługi WebExtrator, najpierw przejdź do [konsoli Ace Data Cloud](https://platform.acedata.cloud/console/applications), aby uzyskać swój token API, który należy zachować na przyszłość.

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

Jeśli nie jesteś zalogowany lub zarejestrowany, automatycznie zostaniesz przekierowany na stronę logowania, aby zarejestrować się i zalogować, a po zakończeniu zostaniesz automatycznie przekierowany z powrotem na bieżącą stronę.

**Jeden token API wystarczy do wywołania wszystkich usług platformy, nie ma potrzeby składania osobnych wniosków dla każdej usługi.** Pierwsze zgłoszenie otrzyma darmowy limit, aby można było bezpłatnie przetestować; w przypadku niewystarczającego limitu można doładować ogólny bilans w [konsoli](https://platform.acedata.cloud/console/coin).

> 📘 Pełna dokumentacja: [Strona usługi WebExtrator →](https://platform.acedata.cloud/service/webextrator)

## Autoryzacja

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

## Parametry żądania

Extract akceptuje **wszystkie** parametry [Render API](development_webextrator_render) (`url`, `user_agent`, `timeout`, `wait_until`, `delay`, `wait_for_selector`, `block_resources`, `headers`, `cookies`, `callback_url`, `bypass_cache`, `cache_ttl_seconds`, `async`), plus dwa pola specyficzne dla Extract:

| Pole            | Typ     | Wymagane | Domyślne                | Opis                                                                                                                                                                                   |
| --------------- | ------- | :------: | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `expected_type` | enum    |     ❌    | automatyczne określenie | Wskazanie typu strony: `product` / `article` / `general`. Pomija URL / tekst heurystycznie, przechodzi bezpośrednio do odpowiedniego gałęzi.                                           |
| `enable_llm`    | boolean |     ❌    | `false`                 | Pozwala na wywołanie LLM ekstrakcji, gdy schema.org nie jest trafione. Na stronach bez JSON-LD, takich jak Amazon / HN / Greenhouse, należy to włączyć, aby uzyskać wyniki typizowane. |

> Gdy strona zawiera schema.org JSON-LD, `enable_llm` jest nieaktywne — deterministyczny mapper zwraca wyniki, nigdy nie marnując wywołania LLM. Otrzymujesz **darmowe** wyniki typizowane.

## Odpowiedź synchronizacyjna

```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": 1777717802.535,
  "elapsed": 2.412,
  "data": {
    "kind": "extract",
    "url": "https://en.wikipedia.org/wiki/Diffbot",
    "finalUrl": "https://en.wikipedia.org/wiki/Diffbot",
    "contentType": "article",
    "title": "Diffbot",
    "description": "Amerykańska firma zajmująca się uczeniem maszynowym i zarządzaniem wiedzą",
    "byline": "Współpracownicy projektów Wikimedia",
    "language": "en",
    "siteName": "Wikipedia",
    "publishedAt": "2007-08-08T05:47:27Z",
    "images": ["https://en.wikipedia.org/static/images/icons/enwiki-25.svg"],
    "links": ["https://en.wikipedia.org/wiki/Machine_learning"],
    "markdown": "# Diffbot\n\nDiffbot jest deweloperem algorytmów uczenia maszynowego ...",
    "text": "Diffbot jest deweloperem algorytmów uczenia maszynowego ...",
    "structured": {
      "schemaOrg": { "primary": { /* typizowane encje */ }, "breadcrumbs": [], "all": [] },
      "openGraph": { "title": "...", "description": "...", "image": "...", "type": "..." },
      "jsonLd": [ /* oryginalny JSON-LD */ ]
    },
    "rawSignals": {
      "hasJsonLd": true,
      "title": "Diffbot - Wikipedia",
      "metaDescription": null,
      "pageStatus": 200,
      "textLength": 11473
    },
    "elapsedMs": 2412
  }
}
```

### Pola górne

| Pole            | Typ       | Opis                                                                                                                      |
| --------------- | --------- | ------------------------------------------------------------------------------------------------------------------------- |
| `kind`          | string    | Stałe `"extract"`.                                                                                                        |
| `url`           | string    | URL, który przesłałeś.                                                                                                    |
| `finalUrl`      | string    | Ostateczny URL po przekierowaniu.                                                                                         |
| `contentType`   | enum      | `product` / `article` / `general`, określane przez `expected_type` → schema.org primary → heurystyka.                     |
| `title`         | string    | `<title>` Readability lub `document.title` po renderowaniu.                                                               |
| `description`   | string?   | Priorytet: `<meta name="description" />` → `og:description` → schema.org / LLM ekstrakcja → skrócenie pierwszego akapitu. |
| `byline`        | string?   | Autor / kanał / firma. Źródło `<meta name="author" />` → schema.org / LLM.                                                |
| `language`      | string?   | `<html lang>`.                                                                                                            |
| `siteName`      | string?   | `og:site_name`.                                                                                                           |
| `publishedAt`   | string?   | ISO 8601. Priorytet: `article:published_time` → `<time datetime>` → schema.org / LLM.                                     |
| `images`        | string\[] | Maksymalnie 50 `<img src />`, przekształcone na absolutne URL, usunięte duplikaty, odrzucone `data:` URI.                 |
| `links`         | string\[] | Maksymalnie 100 zewnętrznych linków, przefiltrowane fragmenty / `javascript:` / `mailto:` / `tel:`.                       |
| `markdown`      | string    | Markdown wyjściowy z Turndown.                                                                                            |
| `text`          | string    | `textContent` wyodrębnione przez Mozilla Readability.                                                                     |
| `structured`    | object    | Pełne wyniki strukturalne, patrz poniżej.                                                                                 |
| `rawSignals`    | object    | Informacje diagnostyczne do debugowania.                                                                                  |
| `cached`        | boolean?  | `true`, gdy trafiono w pamięć podręczną.                                                                                  |
| `cacheStoredAt` | number?   | Znacznik czasu Unix w milisekundach, kiedy wpis pamięci podręcznej został po raz pierwszy zapisany.                       |

### Podpola `data.structured`

| Podpole     | Kiedy się pojawia                                | Opis                                                                                                                |
| ----------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `schemaOrg` | Zawsze                                           | `{ primary, breadcrumbs, all }`. `primary` to najwyższy priorytet typizowanego bytu; gdy nie znaleziono, to `null`. |
| `openGraph` | Zawsze                                           | `{ title, description, image, type }`, pochodzi z `<meta property="og:*" />`.                                       |
| `jsonLd`    | Zawsze                                           | Wszystkie oryginalne tablice JSON z `<script type="application/ld+json">`.                                          |
| `llm`       | Gdy LLM działa i zakończył się sukcesem          | `{ kind, data, model, promptCharCount }`, typizowany wynik zweryfikowany przez Zod.                                 |
| `llmError`  | Gdy LLM działa, ale zakończył się niepowodzeniem | `{ kind, error, model }`, żądanie nie spowoduje awarii, heurystyczny wynik nadal zostanie zwrócony.                 |
| `amazon`    | Gdy URL to `amazon.*`                            | Wyniki starego, dedykowanego narzędzia do pobierania z Amazon (będzie stopniowo wycofywane).                        |

## Zakres mapowania schema.org

Posortowane według priorytetu (gdy trafione, traktowane jako `structured.schemaOrg.primary`):

| Typ schema.org                                                                                             | Rodzaj                    | Pola wyjściowe                                                                                                                                                                           |
| ---------------------------------------------------------------------------------------------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Product`                                                                                                  | produkt                   | `name, sku, gtin, model, color, brand, url, images, offer.{price,currency,availability,condition,seller}, rating.{value,count}, reviews[], properties[]`                                 |
| `Recipe`                                                                                                   | przepis                   | `name, description, image, datePublished, author, cookTime, prepTime, totalTime, recipeYield, ingredients[], instructions[], nutrition, rating, keywords, recipeCategory, recipeCuisine` |
| `VideoObject`                                                                                              | wideo                     | `name, description, thumbnailUrl, uploadDate, duration, embedUrl, contentUrl, channel, interactionCount`                                                                                 |
| `JobPosting`                                                                                               | praca                     | `title, description, datePosted, validThrough, hiringOrganization, jobLocation, baseSalary, employmentType`                                                                              |
| `Event` (w tym `*Event`)                                                                                   | wydarzenie                | `name, description, startDate, endDate, location.{name,address}, organizer, offer.{url,price,currency}`                                                                                  |
| `Article` / `NewsArticle` / `BlogPosting` / `ScholarlyArticle` / `TechArticle` / `Report` / `*NewsArticle` | artykuł                   | `subtype, headline, description, datePublished, dateModified, author, publisher, image[], url, sameAs[]`                                                                                 |
| `FAQPage`                                                                                                  | faq                       | `questions[{question, answer}]`                                                                                                                                                          |
| `BreadcrumbList`                                                                                           | (przypięte do rodzeństwa) | Zawsze wyjście do `structured.schemaOrg.breadcrumbs[]`, nie będzie traktowane jako primary.                                                                                              |

Przetwarzanie mapera:

* Kontener `@graph` (rekurencyjnie rozwijany);
* Tablica `@type` (np. `["Recipe", "NewsArticle"]` — oba rozpoznawane, wygrywa ten o wyższym priorytecie);
* Warianty z prefiksem `http://schema.org/`;
* Zagnieżdżone `Offer` i `AggregateOffer` (ten drugi odczytuje `lowPrice`);
* Względne URL-e obrazów (rozwiązywane do absolutnych na podstawie `finalUrl`).

## Typizowany schemat LLM

Gdy `enable_llm: true` **i** schema.org nie ma primary, ekstraktor na podstawie URL-u heurystycznie
(w lub `expected_type` wskazówka) wybiera jeden z poniższych modeli walidacji Zod Schema:

| Rodzaj       | Heurystyka URL                                                                     | Wymagane pola | Opcjonalne pola                                                                                                                                                              |
| ------------ | ---------------------------------------------------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `article`    | Tekst ≥400 słów i inne nie trafione                                                | `headline`    | `description, byline, publishedAt, language, topics[], sections[{heading,summary}]`                                                                                          |
| `product`    | `amazon.* / ebay.* / aliexpress.* / temu.* / walmart.* / bestbuy.*`                | `name`        | `description, brand, sku, price, currency, availability, rating.{value,count}, bullets[], specifications[{name,value}]`                                                      |
| `discussion` | `news.ycombinator.com / reddit.com / lobste.rs`                                    | `title`       | `author, postedAt, points, commentCount, body, url`                                                                                                                          |
| `recipe`     | `allrecipes / foodnetwork / seriouseats / epicurious / bonappetit / simplyrecipes` | `name`        | `description, author, cookTime, prepTime, totalTime, recipeYield, ingredients[], instructions[], nutrition, rating, keywords[]`                                              |
| `video`      | `youtube.com/watch / youtu.be / vimeo.com/<id> / tiktok.com/@/video`               | `name`        | `description, channel, uploadDate, duration, viewCount, likeCount, thumbnailUrl, transcript`                                                                                 |
| `job`        | `greenhouse.io / lever.co / jobs.* / careers.* / workable.com / bamboohr`          | `title`       | `description, company, location, remote, employmentType, datePosted, validThrough, salaryMin, salaryMax, salaryCurrency, salaryPeriod, responsibilities[], qualifications[]` |

W przypadku sukcesu LLM, również nastąpi "last-resort" uzupełnienie do pól najwyższego poziomu:

* `article` → `description` / `byline` / `publishedAt` / `language`
* `product` → `description`
* `discussion` → `description` (= body pierwsze 280 znaków) / `byline` (= author) / `publishedAt` (= postedAt)
* `recipe` → `description` / `byline` (= author)
* `video` → `description` / `byline` (= channel) / `publishedAt` (= uploadDate)
* `job` → `description` / `byline` (= company) / `publishedAt` (= datePosted)

Uzupełnienie następuje tylko wtedy, gdy źródło danych **nie wypełniło** odpowiadających pól — LLM zawsze jest ostatnią deską ratunku.

## Cache

Te same żądania będą haszowane do tego samego klucza Redis:
`webextrator:cache:extract:<sha256(canonical-json)>`. Klucz cache **ignoruje** `async`,
`bypass_cache`, `cache_ttl_seconds` (to jest przełącznik operacyjny, nie wpływa na odpowiedź). `cookies` /
`headers` **będą** przechowywane w oddzielnych zbiorach.

| Pole                   | Efekt                                                                                                         |
| ---------------------- | ------------------------------------------------------------------------------------------------------------- |
| `bypass_cache: true`   | Pomija odczyt; wynik tej sesji nadal zostanie zapisany w cache, aby następne takie samo żądanie mogło trafić. |
| `cache_ttl_seconds: 0` | Ta odpowiedź **nie będzie cache'owana**.                                                                      |
| `cache_ttl_seconds: N` | Dostosowuje TTL tego wpisu (domyślnie 3600 sekund).                                                           |

Odpowiedzi z trafieniem w cache będą zawierały `data.cached: true` oraz `data.cacheStoredAt: <unix-ms>`.

## Tryb asynchroniczny i callback

Ustawienie `async: true` włącza tryb asynchroniczny (podanie `callback_url` również automatycznie włącza). Platforma natychmiast zwraca (HTTP 200):

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

Po zakończeniu zadania, pełny envelope zostanie `POST` do twojego `callback_url` (jeśli skonfigurowano). Można również
później aktywnie sprawdzić przez [`/webextrator/tasks`](development_webextrator_tasks).

## Przykład

### 1. Artykuł Wikipedia (trafienie schema.org, nie wymaga LLM)

```bash theme={null}
curl -X POST https://api.acedata.cloud/webextrator/extract \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://en.wikipedia.org/wiki/Diffbot",
    "expected_type": "article"
  }'
```

Kluczowe pola `data.structured.schemaOrg.primary`:

```json theme={null}
{
  "kind": "artykuł",
  "subtype": "Artykuł",
  "headline": "Amerykańska firma zajmująca się uczeniem maszynowym i zarządzaniem wiedzą",
  "datePublished": "2007-08-08T05:47:27Z",
  "dateModified": "2025-07-10T20:42:45Z",
  "author": { "name": "Współpracownicy projektów Wikimedia", "type": "Organizacja" },
  "publisher": { "name": "Wikimedia Foundation, Inc." }
}
```

### 2. Strona produktu BestBuy (schema.org hit)

```bash theme={null}
curl -X POST https://api.acedata.cloud/webextrator/extract \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.bestbuy.com/product/apple-airpods-pro-2nd-generation-white/JJ8ZH6TPSW",
    "expected_type": "product"
  }'
```

schema.org wyciąg:

```json theme={null}
{
  "kind": "produkt",
  "name": "Apple - Odnowiony doskonały - AirPods Pro (2. generacja) - Biały",
  "sku": "10845412",
  "model": "MQD83AM/A",
  "color": "Biały",
  "brand": "Apple",
  "offer": { "price": 159.99, "currency": "USD", "availability": "https://schema.org/InStock", "seller": "Best Buy" },
  "rating": { "value": 4.4, "count": 8 }
}
```

### 3. Strona przepisu AllRecipes (z wartościami odżywczymi i krokami)

```bash theme={null}
curl -X POST https://api.acedata.cloud/webextrator/extract \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.allrecipes.com/recipe/16354/easy-meatloaf/"
  }'
```

schema.org wyciąg:

```json theme={null}
{
  "kind": "przepis",
  "name": "Łatwy pasztet",
  "cookTime": "PT60M",
  "totalTime": "PT75M",
  "recipeYield": "8 / 1 (9x5-calowy) pasztet",
  "ingredients": ["1 1/2 funta mielonej wołowiny", "..."],
  "instructions": [{ "text": "Rozgrzej piekarnik do 350°F ..." }, "..."],
  "rating": { "value": 4.7, "count": 9348 }
}
```

### 4. Strona dyskusji HN (bez JSON-LD — wymaga włączenia LLM)

```bash theme={null}
curl -X POST https://api.acedata.cloud/webextrator/extract \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://news.ycombinator.com/item?id=37000000",
    "enable_llm": true
  }'
```

`data.structured.llm.data`:

```json theme={null}
{
  "kind": "dyskusja",
  "title": "Pokaż HN: Nowy sposób na wyciąganie stron internetowych",
  "author": "alice",
  "points": 173,
  "commentCount": 42,
  "body": "Cześć HN, stworzyliśmy samodzielnie hostowaną alternatywę dla API Analizuj Diffbota ..."
}
```

Najwyższe pola również zostały uzupełnione: `byline = "alice"`、`publishedAt = "..."`。

### 5. Strona produktu Amazon (Amazon bez JSON-LD — wymaga włączenia LLM)

```bash theme={null}
curl -X POST https://api.acedata.cloud/webextrator/extract \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.amazon.com/dp/B0BSHF7WHW",
    "expected_type": "product",
    "enable_llm": true
  }'
```

`data.structured.llm.data` (typ `produkt`):

```json theme={null}
{
  "kind": "produkt",
  "name": "Apple 2023 MacBook Pro M2 Pro 14-calowy",
  "brand": "Apple",
  "price": 1799,
  "currency": "USD",
  "bullets": ["Chip Apple M2 Pro z 10-rdzeniowym CPU", "..."],
  "specifications": [{ "name": "Rozmiar wyświetlacza", "value": "14.2 cale" }, "..."]
}
```

### Python (requests)

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

API_KEY = os.environ["ACEDATA_API_KEY"]

resp = requests.post(
    "https://api.acedata.cloud/webextrator/extract",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "url": "https://en.wikipedia.org/wiki/Diffbot",
        "expected_type": "artykuł",
    },
    timeout=120,
)
resp.raise_for_status()
data = resp.json()["data"]

primary = (data.get("structured") or {}).get("schemaOrg", {}).get("primary")
print("contentType:", data["contentType"])
print("title:      ", data["title"])
print("byline:     ", data.get("byline"))
print("publishedAt:", data.get("publishedAt"))
if primary and primary["kind"] == "artykuł":
    print("headline:    ", primary["headline"])
    print("dateModified:", primary.get("dateModified"))
```

### Node.js (fetch)

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

const res = await fetch('https://api.acedata.cloud/webextrator/extract', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://www.allrecipes.com/recipe/16354/easy-meatloaf/',
  }),
});
const { data } = await res.json();
const recipe = data?.structured?.schemaOrg?.primary;
console.log(recipe.name, recipe.cookTime, recipe.ingredients.length, 'rodzaj składników');
```

## Wskazówki i pułapki

* **Jeśli można przekazać `expected_type`, to to zrób.** Darmowa wskazówka, pomijająca heurystyczne oceny, szczególnie przydatna dla stron, których wzór URL nie znajduje się na wbudowanej liście.
* **`enable_llm: true` na stronach z trafieniem schema.org jest darmowe.** LLM jest wywoływane tylko wtedy, gdy schema.org nie ma primary, więc domyślnie jest to również bezpieczne.
* **Podczas debugowania najpierw sprawdź `rawSignals.hasJsonLd`.** Jeśli jest `true`, ale `structured.schemaOrg.primary` jest `null`, oznacza to, że strona używa typu `@type`, którego nasz mapper jeszcze nie pokrył — zgłoś problem, dodamy.
* **`structured.llmError` jest informacyjne.** Żądanie nadal jest udane, a wyniki heurystyczne są nadal zwracane. Sprawdź `llmError.error`, aby zlokalizować przyczynę (przekroczenie czasu, błąd analizy JSON, błąd walidacji Zod).
* **Linki na stronach innych niż artykuły nie będą sortowane według trafności.** Tylko według "maksymalnie 100 pozycji + filtracja nieprawidłowych protokołów" staramy się oczyścić.
* **Hit cache również jest płatny.** Cache jest przeznaczone na opóźnienia i ochronę puli przeglądarek, a nie na oszczędzanie pieniędzy.
