# Fehler, robots.txt-Ablehnungen und Retries

> WebReaderAPI-Fehlercodes im Überblick: robots.txt- und Seiten-Ablehnungen, Timeouts und Credit-Fehler, die Sie wiederholen sollten.

- URL: https://webreaderapi.com/de/docs/errors/
- Zuletzt aktualisiert: 2026-10-22
- Herausgeber: WebReaderAPI (https://webreaderapi.com)

Jeder Fehler hat einen HTTP-Status, ein stabiles `code` und eine lesbare `message`. Keiner von ihnen verbraucht einen Credit. Manche sind einen Retry wert; die Ablehnungen, die von einer Seite kommen, sind endgültig, und wir umgehen sie nie.

**Kurze Antwort — Was bedeuten die WebReaderAPI-Fehlercodes und welche sollte ich wiederholen?**

**WebReaderAPI** Fehler kommen in drei Gruppen, und keiner wird jemals berechnet. Anfrageprobleme (`invalid_url`, `invalid_api_key`, `insufficient_credits`) erfordern eine Korrektur auf Ihrer Seite. Seiten-Entscheidungen (`blocked_by_robots`, `blocked_by_site_policy`, `target_refused`) sind endgültig. Vorübergehende Fehler (`fetch_failed`, `fetch_timeout`, `concurrency_limit`) können mit Backoff wiederholt werden. Credits beginnen bei 0,07 $/1K Seiten, zahlbar mit Krypto ohne KYC.

## Welche Fehlercodes kann die API zurückgeben?

Der Body ist immer `{"error": {"code", "message"}}`, plus `target_status`, wenn die Ablehnung von der Seite kam.

| HTTP | `code` | Ursache | Erneut versuchen? |
| --- | --- | --- | --- |
| 400 | `invalid_url` | Kein http oder https, zu lang oder eine private, lokale oder Cloud-Metadaten-Adresse | Nein: URL korrigieren |
| 400 | `invalid_parameter` | Ein Parameter hat einen Wert außerhalb seiner Liste oder seines Bereichs | Nein: Anfrage korrigieren |
| 401 | `invalid_api_key` | API-Schlüssel fehlt, ist falsch oder wurde widerrufen | Nein: API-Schlüssel prüfen |
| 402 | `insufficient_credits` | Ihr Guthaben hat keine Credits mehr | Nach dem Kauf eines Pakets |
| 403 | `blocked_by_robots` | Die robots.txt der Webseite erlaubt die Seite WebReaderAPI oder allen Robots nicht | Nein: endgültig |
| 403 | `blocked_by_site_policy` | Die Webseite deklariert `Content-Signal: ai-input=no` | Nein: endgültig |
| 422 | `unsupported_content` | Ein Typ, den wir nicht lesen (Video, Archiv), oder eine zu große Datei | Nein |
| 429 | `concurrency_limit` | Zu viele Ihrer Anfragen laufen gleichzeitig | Ja, mit Backoff |
| 502 | `target_refused` | Die Webseite hat abgelehnt: 403, 429, eine Challenge-Seite oder eine Login-Wand; der Status steht in `target_status` | Nein: endgültig |
| 502 | `fetch_failed` | DNS-, TLS- oder Verbindungsfehler, oder die Webseite hat mit 404 oder 410 geantwortet | Ein- oder zweimal, mit Backoff |
| 504 | `fetch_timeout` | Die Webseite hat nicht innerhalb von `timeout` geantwortet | Ja, mit Backoff oder einem längeren Timeout |

## Warum sind robots.txt und Ablehnungen durch Webseiten endgültig?

Weil sie die Entscheidung des Webseiten-Betreibers sind und WebReaderAPI dafür gebaut ist, sie zu befolgen. Wir respektieren robots.txt: Unser Crawler identifiziert sich als WebReaderAPI, befolgt die Regeln, die für ihn oder für alle Roboter geschrieben sind, und liest keine Seite, die eine Website nicht erlaubt. Verweigerte Seiten werden nicht abgerechnet. Wenn eine Website in ihrer robots.txt Content-Signal: ai-input=no deklariert, lesen wir ihre Seiten nicht für Sie.

Wenn eine Webseite eine Anfrage auf andere Weise abweist, mit einem 403, einem 429, einer Challenge-Seite oder einem Login-Formular, erhalten Sie `target_refused` und den Status der Webseite selbst in `target_status`. Wenn eine Website unsere Suchanfrage ablehnt, geben wir ihre Antwort zurück: Wir lösen nie CAPTCHAs, melden uns nie in Konten an und versuchen nie, eine Sperre oder eine Paywall zu umgehen. Dieselbe URL eine Minute später erneut zu versuchen, liefert meist dieselbe Antwort. Behandeln Sie diese Codes daher als Ergebnis, nicht als Fehler: protokollieren und weiter.

## Wie prüfe ich, warum eine Seite abgelehnt wurde?

Öffnen Sie die `/robots.txt` der Webseite und suchen Sie nach einer Gruppe, die `WebReaderAPI` nennt, oder nach der Gruppe `*`, die für alle Robots gilt. Eine Zeile `Disallow`, die zum Pfad passt, erklärt ein `blocked_by_robots`. Eine Zeile wie `Content-Signal: ai-input=no` erklärt ein `blocked_by_site_policy`.

Wir bewahren eine Kopie jeder robots.txt höchstens 24 Stunden auf. Wenn eine Webseite gerade einen Bereich für Robots geöffnet hat, kann die Änderung bis zu einem Tag brauchen, bis sie greift. Webseiten-Betreiber können auf [unserer Crawler-Seite](https://webreaderapi.com/de/bot/) nachlesen, wie sich unser Crawler verhält und wie man ihn erlaubt oder blockiert.

## Wie sollte ich temporäre Fehler erneut versuchen?

Versuchen Sie nur `concurrency_limit`, `fetch_timeout` und ein- oder zweimal `fetch_failed` erneut. Warten Sie vor jedem neuen Versuch und verdoppeln Sie die Wartezeit jedes Mal, mit etwas zufälligem Jitter, damit parallele Worker nicht gleichzeitig erneut versuchen. Hören Sie nach 4 oder 5 Versuchen auf.

Bei `concurrency_limit` ist es besser, weniger Anfragen gleichzeitig zu senden: Jedes Konto hat ein Limit dafür, wie viele Seiten es gleichzeitig liest; Ihr Dashboard zeigt es an, und der Support kann es erhöhen. Bei `fetch_timeout` erhöhen Sie `timeout` auf bis zu 60 Sekunden, bevor Sie eine langsame Webseite erneut versuchen. Wiederholungen kosten nichts, denn ein fehlgeschlagener Versuch wird nie berechnet.

*Python: nur die Fehler erneut versuchen, die sich ändern können*

```python
import os
import random
import time

import requests

API = "https://webreaderapi.com/api/v1/read"
HEADERS = {"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]}
RETRY = {"concurrency_limit", "fetch_timeout", "fetch_failed"}
FINAL = {"blocked_by_robots", "blocked_by_site_policy", "target_refused", "unsupported_content"}


def read_page(url, attempts=5, **options):
    wait = 1.0
    for attempt in range(1, attempts + 1):
        resp = requests.get(API, headers=HEADERS, params={"url": url, **options}, timeout=75)
        if resp.status_code == 200:
            return resp.json()
        error = resp.json().get("error", {})
        code = error.get("code", "unknown")
        if code in FINAL:
            return {"url": url, "skipped": code, "target_status": error.get("target_status")}
        if code not in RETRY or attempt == attempts or (code == "fetch_failed" and attempt >= 3):
            raise RuntimeError(f"{code}: {error.get('message')}")
        time.sleep(wait + random.uniform(0, wait / 2))
        wait = min(wait * 2, 30)
    raise RuntimeError("unreachable")


if __name__ == "__main__":
    print(read_page("https://example.com/blog/first-post", max_chars=20000).get("title"))

```

*Node.js: dieselbe Regel mit exponentiellem Backoff*

```javascript
const RETRY = new Set(['concurrency_limit', 'fetch_timeout', 'fetch_failed']);
const FINAL = new Set(['blocked_by_robots', 'blocked_by_site_policy', 'target_refused', 'unsupported_content']);
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

export async function readPage(url, options = {}, attempts = 5) {
  let wait = 1000;
  for (let attempt = 1; attempt <= attempts; attempt++) {
    const params = new URLSearchParams({ url, ...options });
    const res = await fetch(`https://webreaderapi.com/api/v1/read?${params}`, {
      headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}` },
    });
    const body = await res.json();
    if (res.ok) return body;
    const code = body.error?.code ?? 'unknown';
    if (FINAL.has(code)) return { url, skipped: code, target_status: body.error.target_status };
    if (!RETRY.has(code) || attempt === attempts) throw new Error(`${code}: ${body.error?.message}`);
    await sleep(wait + Math.random() * (wait / 2));
    wait = Math.min(wait * 2, 30000);
  }
}

```

## Was ist mit Fehlern innerhalb eines Batch oder Crawls?

Ein Job stoppt nicht, weil eine Seite fehlschlägt. Diese Seite erscheint in `results` als `{url, error}` mit denselben Codes wie oben, und sie kostet nichts. Ein Crawl, der auf einen Abschnitt `blocked_by_robots` stößt, liest einfach den Rest der Website.

Zählen Sie am Ende eines Jobs die Fehlercodes. Viele `target_refused` auf einer Website bedeuten, dass die Website automatisierte Reader nicht akzeptiert; viele `fetch_timeout` bedeuten, dass sie langsam ist, und ein längeres `timeout` in den Job-Optionen kann helfen.

## Fehler: häufige Fragen

### Wird mir eine Seite berechnet, die robots.txt blockiert?

Nein. 1 Credit = 1 gelesene Seite ohne Browser; 2 Credits, wenn die Seite einen Browser braucht, um JavaScript auszuführen. Eine Suchanfrage, die fehlschlägt oder die eine robots.txt einer Website verweigert, wird nicht abgerechnet. Dasselbe gilt für jeden anderen Fehler auf dieser Seite.

### Können Sie eine Seite lesen, die Ihren Crawler blockiert, wenn ich es verlange?

Nein. Wir folgen der Entscheidung des Website-Betreibers, und die Richtlinie ist für jeden Kunden gleich. Wenn Sie die Website besitzen, fügen Sie eine Regel für `WebReaderAPI` in Ihre robots.txt ein; die [Crawler-Seite](https://webreaderapi.com/de/bot/) zeigt, wie.

### Warum bekomme ich fetch_failed für eine Seite, die existiert?

Die Website war möglicherweise ausgefallen, hat eine TLS-Verbindung nur langsam akzeptiert oder gibt automatisierten Clients 404 zurück. Versuchen Sie es ein- oder zweimal mit Backoff erneut. Wenn es weiterhin fehlschlägt, prüfen Sie die Adresse in einem Browser.

### Was sollte mein Agent dem Nutzer nach einer Ablehnung sagen?

Etwas Einfaches, etwa dass die Website das automatisierte Lesen dieser Seite nicht erlaubt. Lassen Sie das Modell dann andere Quellen nutzen. Den Fehlercode als Tool-Ergebnis zurückzugeben, reicht für die meisten Modelle.

---

WebReaderAPI: WebReaderAPI ist eine Web-Reader-API für KI-Agenten, die jede öffentliche Webseite in sauberes Markdown umwandelt und die Sie mit Krypto bezahlen – ohne ID-Upload. Prepaid-Credits ab 0,07 $/1K Seiten verfallen nie, und robots.txt wird respektiert. Ohne KYC – keine ID, kein Selfie, keine Dokumente. Mit Krypto bezahlen.
