Bez KYC — bez dowodu, bez selfie, bez dokumentów. Płatność kryptowalutą: BTC, USDT, USDC, ETH, SOL, LTC
Język: Polski
Uzyskaj klucz API

Dokumentacja · zadania

Batch i crawl API: czytaj wiele URL-i lub całą witrynę

Dwa endpointy uruchamiają zadania w tle: /batch dla listy do 100 URL-i, /crawl dla jednej witryny. Oba zwracają ID zadania; strony odbierasz z /jobs/{job_id}, po jednej stronie wyników naraz.

Ostatnia aktualizacja: · 7 min czytania

Szybka odpowiedź

Jak scrawlować witrynę do Markdown za pomocą WebReaderAPI?

Wyślij URL startowy do POST https://webreaderapi.com/api/v1/crawl z parametrem strony limit. WebReaderAPI czyta witrynę w tle, tylko w obrębie tej samej domeny, zgodnie z jej sitemap, robots.txt i Crawl-delay, do 10 000 stron na zadanie. Odbieraj strony Markdown z zadania, po jednej stronie wyników naraz. Każde odczytanie strony kosztuje 1 kredyt (2 z przeglądarką), od 0,07 USD/1K stron stan na październik 2026. Bez KYC; płatność kryptowalutą.

Zadania w skrócie

BatchDo 100 URL-i na jedno zadanie wsadowe: POST https://webreaderapi.com/api/v1/batch
CrawlCrawling jednej witryny na zadanie, do 10 000 stron, zgodnie z jej sitemapą, jej robots.txt i jej Crawl-delay: POST https://webreaderapi.com/api/v1/crawl
WynikiGET https://webreaderapi.com/api/v1/jobs/{job_id}, potem ?cursor=… po następną stronę wyników
RozliczanieKażde odczytanie strony jest rozliczane jak wywołanie /read; strony pominięte przez robots.txt i nieudane strony nic nie kosztują
Zakres crawluJedna domena; linki do innych domen są wymieniane, ale nie czytane
Anulowanie zadaniaNiedostępne w v1: ustaw limit na największą liczbę stron, za którą jesteś gotów zapłacić

Uruchom zadanie batch

POST/api/v1/batch

Czyta w tle do 100 URL-i z tymi samymi opcjami. Opcje używają nazw i wartości z /read. Odpowiedzią jest ID zadania; wartości są przykładowe.

Uwierzytelnianie: klucz API w nagłówku Authorization: Bearer API_KEY.

Treść zapytania

PoleTypWymaganeOpis
urlsarray of stringsTakOd 1 do 100 adresów URL http lub https. Duplikaty są odczytywane raz.
optionsobjectNieDowolny parametr /read oprócz url: format, main_content, render, include_links, include_images, country, max_chars, timeout.
Przykład: three articles as Markdown
{
  "urls": [
    "https://example.com/blog/post-1",
    "https://example.com/blog/post-2",
    "https://example.org/news/launch"
  ],
  "options": {
    "format": "markdown",
    "max_chars": 50000
  }
}

Odpowiedź 202 Accepted

{
  "job_id": "job_5c1e8a90d2"
}

Przykłady kodu

curl
curl -s "https://webreaderapi.com/api/v1/batch" \
  -H "Authorization: Bearer $WEBREADER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://example.com/blog/post-1", "https://example.com/blog/post-2"], "options": {"format": "markdown"}}'
Python
import os
import requests

resp = requests.post(
    "https://webreaderapi.com/api/v1/batch",
    headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
    json={"urls": ["https://example.com/blog/post-1", "https://example.com/blog/post-2"], "options": {"format": "markdown"}},
    timeout=30,
)
print(resp.json()["job_id"])
Node.js
const res = await fetch('https://webreaderapi.com/api/v1/batch', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ urls: ['https://example.com/blog/post-1', 'https://example.com/blog/post-2'], options: { format: 'markdown' } }),
});
console.log((await res.json()).job_id);

Rozpocznij zadanie crawlowania

POST/api/v1/crawl

Odczytuje jedną witrynę od URL startowego, wszerz. Crawler pozostaje w domenie URL startowego, używa sitemapy wskazanej w robots.txt lub znalezionej pod /sitemap.xml i respektuje robots.txt oraz Crawl-delay. Wartości są przykładowe.

Uwierzytelnianie: klucz API w nagłówku Authorization: Bearer API_KEY.

Treść zapytania

PoleTypWymaganeOpis
urlstringTakStrona startowa, np. strona główna witryny z dokumentacją.
limitintegerNieMaksymalna liczba stron do odczytania, do 10 000. Zadanie kończy się po osiągnięciu tej liczby.
max_depthintegerNieMaksymalna liczba kroków po linkach od URL startowego.
include_pathsarray of stringsNieProste wzorce ścieżek do zachowania, np. /docs/*.
exclude_pathsarray of stringsNieProste wzorce ścieżek do pominięcia, np. /blog/tag/*.
optionsobjectNieDowolny parametr /read oprócz url, stosowany do każdej strony.
Przykład: the docs section of a site, 500 pages at most
{
  "url": "https://docs.example.com/",
  "limit": 500,
  "max_depth": 3,
  "include_paths": [
    "/docs/*"
  ],
  "exclude_paths": [
    "/docs/archive/*"
  ],
  "options": {
    "format": "markdown"
  }
}

Odpowiedź 202 Accepted

{
  "job_id": "job_8b27f41c0e"
}

Przykłady kodu

curl
curl -s "https://webreaderapi.com/api/v1/crawl" \
  -H "Authorization: Bearer $WEBREADER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://docs.example.com/", "limit": 500, "include_paths": ["/docs/*"]}'
Python
import os
import requests

resp = requests.post(
    "https://webreaderapi.com/api/v1/crawl",
    headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
    json={"url": "https://docs.example.com/", "limit": 500, "include_paths": ["/docs/*"]},
    timeout=30,
)
print(resp.json()["job_id"])
Node.js
const res = await fetch('https://webreaderapi.com/api/v1/crawl', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ url: 'https://docs.example.com/', limit: 500, include_paths: ['/docs/*'] }),
});
console.log((await res.json()).job_id);

Pobierz status zadania i wyniki

GET/api/v1/jobs/{job_id}

Zwraca status zadania oraz kolejne gotowe wyniki. Każdy element results to albo pełna odpowiedź /read, albo {url, error} dla strony, której nie udało się odczytać. Gdy next_cursor występuje, wywołaj ponownie z cursor ustawionym na tę wartość; gdy go nie ma, nie ma jeszcze kolejnych gotowych wyników. Wartości są przykładowe.

Uwierzytelnianie: klucz API w nagłówku Authorization: Bearer API_KEY.

Parametry

NazwaWTypWymaganeOpis
job_idpathstringTakID zwrócone przez /batch lub /crawl.
cursorquerystringNieWartość next_cursor z poprzedniego wywołania, aby pobrać kolejne wyniki.

Odpowiedź 200

{
  "job_id": "job_8b27f41c0e",
  "status": "running",
  "results": [
    {
      "url": "https://docs.example.com/docs/install",
      "final_url": "https://docs.example.com/docs/install",
      "status_code": 200,
      "rendered": false,
      "credits_used": 1,
      "title": "Install",
      "markdown": "# Install\n\nRun the installer...",
      "word_count": 418
    },
    {
      "url": "https://docs.example.com/docs/private",
      "error": {
        "code": "blocked_by_robots",
        "message": "robots.txt disallows this page for WebReaderAPI."
      }
    }
  ],
  "next_cursor": "c_000002",
  "credits_used": 1
}

Przykłady kodu

curl
curl -sG "https://webreaderapi.com/api/v1/jobs/job_8b27f41c0e" \
  -H "Authorization: Bearer $WEBREADER_API_KEY" \
  -d cursor=c_000002
Python
import os
import requests

resp = requests.get(
    "https://webreaderapi.com/api/v1/jobs/job_8b27f41c0e",
    headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
    params={"cursor": "c_000002"},
    timeout=30,
)
job = resp.json()
print(job["status"], len(job["results"]), job.get("next_cursor"))
Node.js
const res = await fetch('https://webreaderapi.com/api/v1/jobs/job_8b27f41c0e?cursor=c_000002', {
  headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}` },
});
const job = await res.json();
console.log(job.status, job.results.length, job.next_cursor);

Jak czekać na zakończenie zadania?

Odpytuj /jobs/{job_id} i zachowuj kursor. Przetwarzaj otrzymane wyniki, a następnie wywołaj ponownie z cursor ustawionym na next_cursor. Gdy next_cursor nie występuje, a status to done, masz już wszystko; gdy go nie ma, a zadanie nadal jest w stanie running, odczekaj i zapytaj ponownie z tym samym kursorem.

Zacznij odpytwać co 2 sekundy i podwajaj czas oczekiwania do 30 sekund, dopóki nie pojawi się nic nowego. Crawl, który respektuje Crawl-delay witryny, może potrwać, więc długie oczekiwanie jest normalne i nic nie kosztuje.

Python: odpytuj zadanie i zapisuj każdą stronę jako plik .md
import os
import pathlib
import re
import time

import requests

JOBS = "https://webreaderapi.com/api/v1/jobs"
HEADERS = {"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]}


def save_job(job_id, folder="pages"):
    out = pathlib.Path(folder)
    out.mkdir(exist_ok=True)
    cursor, wait, saved = None, 2, 0
    while True:
        params = {"cursor": cursor} if cursor else {}
        job = requests.get(f"{JOBS}/{job_id}", headers=HEADERS, params=params, timeout=30).json()
        for item in job["results"]:
            if "error" in item:
                print("skipped", item["url"], item["error"]["code"])
                continue
            name = re.sub(r"[^a-z0-9]+", "-", item["final_url"].lower()).strip("-")[:120]
            (out / f"{name}.md").write_text(item["markdown"], encoding="utf-8")
            saved += 1
        if job.get("next_cursor"):
            cursor, wait = job["next_cursor"], 2
            continue
        if job["status"] == "done":
            return saved
        time.sleep(wait)
        wait = min(wait * 2, 30)


if __name__ == "__main__":
    print(save_job("job_8b27f41c0e"), "pages saved")

Które strony odczytuje crawl?

Crawl zaczyna się od Twojego URL i posuwa się na zewnątrz o jeden krok po linkach naraz, wszerz, do max_depth. Odczytuje też sitemapę witryny, z adresu podanego w robots.txt lub z /sitemap.xml, aby znaleźć strony, do których prowadzi niewiele linków.

  • Tylko ta sama domena. Linki do innych domen są wymieniane w wynikach, gdy poprosisz o include_links, ale nie są odczytywane.
  • Filtry ścieżek. include_paths i exclude_paths przyjmują proste wzorce, np. /blog/*.
  • Jedna kopia na stronę. Gdy witryna deklaruje kanoniczny URL, strona osiągnięta przez kilka adresów jest odczytywana raz.
  • Twardy limit. Zadanie kończy się po odczytaniu limit stron.

Jak crawl respektuje witrynę?

Każde zapytanie niesie User-Agent WebReaderAPI/1.0 (+https://webreaderapi.com/bot/), a crawler przestrzega reguł robots.txt dla WebReaderAPI lub dla wszystkich robotów, gdy żaden go nie wskazuje. Zablokowane strony są pomijane i pojawiają się w results z błędem blocked_by_robots; nic nie kosztują.

Gdy robots.txt ustawia Crawl-delay, crawler czeka tyle między dwoma zapytaniami do witryny. Jeśli witryna zadeklaruje Content-Signal: ai-input=no w swoim robots.txt, nie czytamy jej stron dla Ciebie. Jeśli witryna odrzuci nasze zapytanie, zwracamy jej odpowiedź: nigdy nie rozwiązujemy CAPTCHA, nie logujemy się do kont ani nie próbujemy obejść blokady lub paywalla.

Ile kosztuje crawl?

Każda odczytana strona kosztuje tyle, co wywołanie /read: 1 kredyt, 2, jeśli strona wymagała przeglądarki, plus 10 z country. Pominięte i nieudane strony są darmowe. Pole credits_used zadania sumuje to, co zostało już rozliczone.

Witryna z dokumentacją licząca 500 stron odczytana bez przeglądarki zużywa około 500 kredytów, co pakiet 10 000 stron (3,75 USD) pokrywa wielokrotnie. Ponieważ zadania nie można anulować w v1, limit to Twój limit wydatków: ustaw go na maksymalną liczbę stron, za które jesteś gotowy zapłacić.

Batch i crawl: najczęstsze pytania

Czy używać /batch czy wielu wywołań /read?

Użyj /batch, gdy masz już URL-e i nie potrzebujesz każdej odpowiedzi od razu. Oszczędza Ci zarządzania współbieżnością i ponawianiem. Użyj /read, gdy agent potrzebuje jednej strony teraz.

Jak długo przechowywane są wyniki zadań?

Odbieraj je, gdy tylko będą gotowe. Wyniki czekają, aż je pobierzesz; po dostarczeniu nie jest przechowywana żadna kopia treści strony, więc zapisz to, czego potrzebujesz, po swojej stronie.

Czy crawl może podążać za linkami do innych witryn?

Nie. Crawl odczytuje jedną domenę. Inne domeny pojawiają się jako linki, gdy o nie poprosisz, a te URL-e możesz wysłać do /batch, jeśli chcesz je odczytać.

Czy mogę zatrzymać rozpoczęty crawl?

Nie w v1. Zadanie zatrzymuje się na limit stronach, więc wybierz limit odpowiadający Twojemu budżetowi. Strony już odczytane pozostają rozliczone; strony nigdy nieodczytane nic nie kosztują.

Od 0,07 USD/1K stron · bez KYC

Uzyskaj klucz API