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 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.
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"))
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 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.