# Batch ve crawl API: çok sayıda URL veya tüm bir siteyi okuyun

> Batch ve crawl API referansı: iş başına 100 URL'ye veya 10.000 sayfaya kadar siteyi okuyun, robots.txt ve Crawl-delay'e uyulur. KYC yok, kripto ile ödeme.

- URL: https://webreaderapi.com/tr/docs/crawl/
- Son güncelleme: 2026-10-22
- Yayıncı: WebReaderAPI (https://webreaderapi.com)

İki endpoint arka plan işleri başlatır: 100 URL'ye kadar bir liste için `/batch`, tek bir web sitesi için `/crawl`. İkisi de bir iş ID'si döndürür; sayfaları `/jobs/{job_id}` üzerinden, her seferinde bir sonuç sayfası olarak toplarsınız.

**Hızlı yanıt — WebReaderAPI ile bir web sitesini nasıl Markdown'a dönüştürürüm?**

Başlangıç URL'sini bir sayfa `limit` ile `POST https://webreaderapi.com/api/v1/crawl` adresine gönderin. **WebReaderAPI** siteyi arka planda okur, yalnızca aynı alan adında, sitemap'ini, robots.txt'ini ve Crawl-delay'ini izleyerek, iş başına 10.000 sayfaya kadar. Markdown sayfalarını işten, her seferinde bir sonuç sayfası olarak toplayın. Her sayfa okuma 1 kredi (tarayıcı ile 2) tutar, Ekim 2026 itibarıyla $0,07/1K sayfa'den. KYC yok; kripto ile ödeme.

## İşlere kısa bir bakış

| Özellik | Değer |
| --- | --- |
| Batch | Toplu iş başına 100 URL'ye kadar: `POST https://webreaderapi.com/api/v1/batch` |
| Tarama (crawl) | İş başına bir web sitesi tarama (crawl), 10.000 sayfaya kadar, sitemap'ini, robots.txt'ini ve Crawl-delay'ini izleyerek: `POST https://webreaderapi.com/api/v1/crawl` |
| Sonuçlar | `GET https://webreaderapi.com/api/v1/jobs/{job_id}`, ardından bir sonraki sonuç sayfası için `?cursor=…` |
| Faturalandırma | Her sayfa okuma bir `/read` çağrısı gibi faturalandırılır; robots.txt tarafından atlanan sayfalar ve başarısız sayfalar ücretsizdir |
| Bir crawl'ın kapsamı | Tek alan adı; diğer alan adlarına bağlantılar listelenir ancak okunmaz |
| Bir işi iptal etme | v1'de yok: ödemeye hazır olduğunuz en fazla sayfa sayısını `limit` olarak ayarlayın |

## Bir batch işi başlatın

`POST /api/v1/batch`

Aynı seçeneklerle 100 URL'ye kadar arka planda okur. Seçenekler [/read](https://webreaderapi.com/tr/docs/read/) adlarını ve değerlerini kullanır. Yanıt iş ID'sidir; değerler örnektir.

Kimlik doğrulama: `Authorization: Bearer API_KEY` header'ında API anahtarı.

**İstek gövdesi**

| Alan | Tür | Zorunlu | Açıklama |
| --- | --- | --- | --- |
| `urls` | array of strings | Evet | 1 ila 100 arası http veya https URL'si. Yinelenenler bir kez okunur. |
| `options` | object | Hayır | `url` dışında herhangi bir `/read` parametresi: `format`, `main_content`, `render`, `include_links`, `include_images`, `country`, `max_chars`, `timeout`. |

*Örnek: three articles as Markdown*

```json
{
  "urls": [
    "https://example.com/blog/post-1",
    "https://example.com/blog/post-2",
    "https://example.org/news/launch"
  ],
  "options": {
    "format": "markdown",
    "max_chars": 50000
  }
}
```

**Yanıt** `202 Accepted`

```json
{
  "job_id": "job_5c1e8a90d2"
}
```

*curl*

```bash
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*

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

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

## Bir tarama (crawl) işi başlatın

`POST /api/v1/crawl`

Başlangıç URL'sinden tek bir web sitesini genişlik öncelikli olarak okur. Tarayıcı (crawler) başlangıç URL'sinin alan adında kalır, robots.txt içinde belirtilen veya `/sitemap.xml` adresinde bulunan sitemap'i kullanır ve robots.txt ile Crawl-delay kurallarına uyar. Değerler örnektir.

Kimlik doğrulama: `Authorization: Bearer API_KEY` header'ında API anahtarı.

**İstek gövdesi**

| Alan | Tür | Zorunlu | Açıklama |
| --- | --- | --- | --- |
| `url` | string | Evet | Başlangıç sayfası; örneğin bir dokümantasyon sitesinin ana sayfası. |
| `limit` | integer | Hayır | Okunacak en fazla sayfa sayısı, 10.000'e kadar. İş bu sayıya ulaştığında durur. |
| `max_depth` | integer | Hayır | Başlangıç URL'sinden en fazla kaç bağlantı adımı uzakta gidileceği. |
| `include_paths` | array of strings | Hayır | Tutulacak basit yol kalıpları; örneğin `/docs/*`. |
| `exclude_paths` | array of strings | Hayır | Atlanacak basit yol kalıpları; örneğin `/blog/tag/*`. |
| `options` | object | Hayır | Her sayfaya uygulanan, `url` dışında herhangi bir `/read` parametresi. |

*Örnek: the docs section of a site, 500 pages at most*

```json
{
  "url": "https://docs.example.com/",
  "limit": 500,
  "max_depth": 3,
  "include_paths": [
    "/docs/*"
  ],
  "exclude_paths": [
    "/docs/archive/*"
  ],
  "options": {
    "format": "markdown"
  }
}
```

**Yanıt** `202 Accepted`

```json
{
  "job_id": "job_8b27f41c0e"
}
```

*curl*

```bash
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*

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

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

## İş durumunu ve sonuçları alın

`GET /api/v1/jobs/{job_id}`

İşin durumunu ve hazır olan sonraki sonuçları döndürür. `results` dizisindeki her öğe ya tam bir `/read` yanıtıdır ya da okunamayan bir sayfa için `{url, error}`. `next_cursor` mevcutsa, `cursor` değerini ona ayarlayarak tekrar çağırın; yoksa henüz hazır başka sonuç yoktur. Değerler örnektir.

Kimlik doğrulama: `Authorization: Bearer API_KEY` header'ında API anahtarı.

**Parametreler**

| Ad | Konum | Tür | Zorunlu | Açıklama |
| --- | --- | --- | --- | --- |
| `job_id` | path | string | Evet | `/batch` veya `/crawl` tarafından döndürülen ID. |
| `cursor` | query | string | Hayır | Sonraki sonuçları almak için önceki çağrıdaki `next_cursor` değeri. |

**Yanıt** `200`

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

*curl*

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

*Python*

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

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

## Bir işin bitmesini nasıl beklerim?

`/jobs/{job_id}` çağrısını yoklayıp cursor'ı koruyun. Gelen sonuçları işleyin, ardından `cursor` değerini `next_cursor` olarak ayarlayarak tekrar çağırın. `next_cursor` yoksa ve `status` `done` ise, her şey elinizde demektir; yoksa ve iş hâlâ `running` ise, bekleyip aynı cursor ile yeniden sorun.

Yoklamaya her 2 saniyede bir başlayın ve yeni bir şey gelmediği sürece beklemeyi 30 saniyeye kadar ikiye katlayın. Bir sitenin Crawl-delay değerine uyan bir tarama biraz zaman alabilir, yani uzun bir bekleme normaldir ve hiçbir ücrete tabi değildir.

*Python: bir işi yoklayın ve her sayfayı .md dosyası olarak kaydedin*

```python
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")

```

## Bir tarama hangi sayfaları okur?

Bir tarama URL'nizden başlar ve genişlik öncelikli olarak, `max_depth` sayısına kadar, her seferinde bir bağlantı adımı dışa doğru ilerler. Ayrıca az sayıda bağlantının işaret ettiği sayfaları bulmak için sitenin sitemap'ini, robots.txt içinde verilen adresten veya `/sitemap.xml` adresinden okur.

- **Yalnızca aynı alan adı.** Diğer alan adlarına giden bağlantılar, `include_links` istediğinizde sonuçlarda listelenir ancak okunmaz.
- **Yol filtreleri.** `include_paths` ve `exclude_paths`, `/blog/*` gibi basit kalıpları alır.
- **Her sayfa için tek kopya.** Bir site canonical URL bildirdiğinde, birden fazla adres üzerinden ulaşılan bir sayfa bir kez okunur.
- **Kesin bir durma noktası.** İş, `limit` sayfa okuduğunda sona erer.

## Bir tarama siteye nasıl saygı gösterir?

Her istek `WebReaderAPI/1.0 (+https://webreaderapi.com/bot/)` User-Agent'ini taşır ve tarayıcı, robots.txt kurallarına `WebReaderAPI` için veya hiçbiri onu adlandırmıyorsa tüm botlar için uyar. İzin verilmeyen sayfalar atlanır ve `results` içinde `blocked_by_robots` hatasıyla görünür; hiçbir ücrete tabi değildir.

robots.txt bir `Crawl-delay` belirlediğinde, tarayıcı siteye yapılan iki istek arasında bu süre kadar bekler. Bir site robots.txt'inde Content-Signal: ai-input=no bildirirse, sayfalarını sizin için okumayız. Bir site isteğimizi reddederse, verdiği yanıtı döndürürüz: CAPTCHA'ları asla çözmeyiz, hesaplara giriş yapmayız veya bir engeli ya da ödeme duvarını aşmaya çalışmayız.

## Bir tarama ne kadar tutar?

Okunan her sayfa, bir `/read` çağrısının tutacağı kadar tutar: 1 kredi, sayfa bir tarayıcı gerektirdiyse 2, `country` ile birlikte 10 daha. Atlanan ve başarısız sayfalar ücretsizdir. İşin `credits_used` değeri, o ana kadar faturalananı toplar.

Tarayıcı olmadan okunan 500 sayfalık bir dokümantasyon sitesi yaklaşık 500 kredi kullanır; 10.000 sayfa paketi ($3,75) bunu çok kez karşılar. v1'de bir iş iptal edilemediğinden `limit` sizin harcama sınırınızdır: ödemeye hazır olduğunuz en fazla sayfa sayısına ayarlayın.

## Batch ve tarama: sık sorulan sorular

### /batch mi yoksa birçok /read çağrısı mı kullanmalıyım?

URL'ler zaten elinizdeyse ve her yanıta tek tek ihtiyacınız yoksa `/batch` kullanın. Bu, eşzamanlılık ve yeniden denemeleri yönetmekten sizi kurtarır. Bir agent'ın şu anda tek bir sayfaya ihtiyacı olduğunda `/read` kullanın.

### İş sonuçları ne kadar saklanır?

Hazır olur olmaz toplayın. Sonuçlar siz onları çekene kadar bekler; teslim edildikten sonra sayfa içeriğinin hiçbir kopyası saklanmaz, bu yüzden ihtiyacınız olanı kendi tarafınızda saklayın.

### Bir tarama başka web sitelerine giden bağlantıları takip edebilir mi?

Hayır. Bir tarama tek bir alan adı okur. Diğer alan adları, istediğinizde bağlantı olarak görünür ve okunmalarını istiyorsanız bu URL'leri `/batch` adresine gönderebilirsiniz.

### Başlamış bir taramayı durdurabilir miyim?

v1'de hayır. İş `limit` sayfada durur, bu yüzden bütçenize uyan bir sınır seçin. Zaten okunan sayfalar faturalanmış kalır; hiç okunmayan sayfalar ücretsizdir.

---

WebReaderAPI: WebReaderAPI, AI ajanları için bir web reader API'sidir; herkese açık herhangi bir web sayfasını temiz Markdown'a dönüştürür ve kimlik yüklemeden kripto ile ödenir. $0,07/1K sayfa başlangıçlı ön ödemeli kreditler asla süresi dolmaz ve robots.txt'e uyulur. KYC yok — kimlik yok, selfie yok, belge yok. Kripto ile ödeme yapın.
