Hızlı yanıt
WebReaderAPI hata kodları ne anlama gelir ve hangilerini yeniden denemeliyim?
WebReaderAPI hataları üç grupta gelir ve hiçbiri asla ücretlendirilmez. İstek sorunları (invalid_url, invalid_api_key, insufficient_credits) sizin tarafınızda bir düzeltme gerektirir. Site kararları (blocked_by_robots, blocked_by_site_policy, target_refused) kesindir. Geçici hatalar (fetch_failed, fetch_timeout, concurrency_limit) backoff ile yeniden denenebilir. Krediler $0,07/1K sayfa değerinden başlar, KYC olmadan kripto ile ödenir.
API hangi hata kodlarını döndürebilir?
Gövde her zaman {"error": {"code", "message"}} olur, ret siteden geldiğinde ayrıca target_status eklenir.
| HTTP | code | Neden | Yeniden denemek ister misiniz? |
|---|---|---|---|
| 400 | invalid_url | http veya https değil, çok uzun ya da özel, yerel veya bulut metadata adresi | Hayır: URL'yi düzeltin |
| 400 | invalid_parameter | Bir parametrenin değeri listesinin veya aralığının dışında | Hayır: isteği düzeltin |
| 401 | invalid_api_key | API anahtarı eksik, yanlış veya iptal edilmiş | Hayır: API anahtarını kontrol edin |
| 402 | insufficient_credits | Bakiyenizde kredi kalmadı | Bir kredi paketi satın aldıktan sonra |
| 403 | blocked_by_robots | Sitenin robots.txt dosyası sayfaya WebReaderAPI için veya tüm robotlar için izin vermiyor | Hayır: kesin sonuç |
| 403 | blocked_by_site_policy | Site Content-Signal: ai-input=no bildiriyor | Hayır: kesin sonuç |
| 422 | unsupported_content | Okumadığımız bir tür (video, arşiv) veya çok büyük bir dosya | Hayır |
| 429 | concurrency_limit | Aynı anda çalışan istekleriniz çok fazla | Evet, geri çekilmeyle |
| 502 | target_refused | Site reddetti: 403, 429, bir doğrulama sayfası veya giriş duvarı; durum kodu target_status içinde | Hayır: kesin sonuç |
| 502 | fetch_failed | DNS, TLS veya bağlantı hatası ya da site 404 veya 410 yanıtı verdi | Bir veya iki kez, geri çekilmeyle |
| 504 | fetch_timeout | Site timeout içinde yanıt vermedi | Evet, geri çekilmeyle veya daha uzun bir timeout ile |
robots.txt ve site retleri neden kesin sonuçtur?
Çünkü bunlar site sahibinin kararıdır ve WebReaderAPI buna uymak için geliştirilmiştir. robots.txt'e uyarız: crawler'ımız kendini WebReaderAPI olarak tanıtır, kendisi için veya tüm robotlar için yazılmış kurallara uyar ve bir sitenin izin vermediği sayfayı okumaz. Reddedilen sayfalar için ücret alınmaz. Bir site robots.txt'inde Content-Signal: ai-input=no bildirirse, sayfalarını sizin için okumayız.
Bir site isteği başka bir şekilde geri çevirdiğinde, 403, 429, bir doğrulama sayfası veya giriş formuyla, target_refused ve sitenin kendi durum kodunu target_status içinde alırsını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. Aynı URL'yi bir dakika sonra yeniden denemek genellikle aynı yanıtı verir, bu yüzden bu kodları başarısızlık değil sonuç olarak değerlendirin: kaydedin ve devam edin.
Bir sayfanın neden reddedildiğini nasıl kontrol ederim?
Sitenin /robots.txt dosyasını açın ve WebReaderAPI adını belirten bir grup ya da tüm robotlar için geçerli olan * grubunu arayın. Yola uyan bir Disallow satırı bir blocked_by_robots durumunu açıklar. Content-Signal: ai-input=no gibi bir satır ise bir blocked_by_site_policy durumunu açıklar.
Her robots.txt dosyasının bir kopyasını en fazla 24 saat tutuyoruz. Bir site bir bölümü robotlara yeni açtıysa, değişikliğin uygulanması bir güne kadar sürebilir. Site sahipleri, crawler'ımızın nasıl davrandığını ve ona nasıl izin verileceğini veya nasıl engelleneceğini crawler sayfamızda okuyabilir.
Geçici hataları nasıl yeniden denemeliyim?
Yalnızca concurrency_limit, fetch_timeout ve bir veya iki kez fetch_failed kodlarını yeniden deneyin. Her yeni denemeden önce bekleyin ve her seferinde bekleme süresini ikiye katlayın; paralel çalışanların aynı anda yeniden denememesi için küçük bir rastgele sapma ekleyin. 4 veya 5 denemeden sonra durun.
concurrency_limit için daha iyi çözüm, aynı anda daha az istek göndermektir: Her hesabın aynı anda okuyabileceği sayfa sayısına bir limit vardır; paneliniz bunu gösterir ve destek ekibi bunu yükseltebilir. fetch_timeout için yavaş bir siteyi yeniden denemeden önce timeout değerini 60 saniyeye kadar artırın. Yeniden denemeler ücretsizdir, çünkü başarısız bir deneme hiçbir zaman faturalandırılmaz.
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);
}
}
Toplu işlem veya tarama içindeki hatalar ne olacak?
Bir sayfa başarısız olduğu için iş durmaz. O sayfa results içinde {url, error} olarak, yukarıdaki aynı kodlarla görünür ve hiçbir ücrete tabi değildir. Bir bölümde blocked_by_robots ile karşılaşan bir tarama, sitenin geri kalanını okumaya devam eder.
İşin sonunda hata kodlarını sayın. Tek bir sitede çok sayıda target_refused, sitenin otomatik okuyucuları kabul etmediği anlamına gelir; çok sayıda fetch_timeout ise sitenin yavaş olduğunu gösterir ve iş seçeneklerinde daha uzun bir timeout yardımcı olabilir.
Hatalar: sık sorulan sorular
robots.txt tarafından engellenen bir sayfa için ücret alınıyor mu?
Hayır. 1 kredi = tarayıcı olmadan 1 sayfa okuma; sayfa JavaScript render etmek için tarayıcı gerektiriyorsa 2 kredi. Başarısız olan veya bir sitenin robots.txt'inin reddettiği istek için ücret alınmaz. Bu sayfadaki diğer tüm hatalar için de aynısı geçerlidir.
İstersem crawler'ınızı engelleyen bir sayfayı okuyabilir misiniz?
Hayır. Site sahibinin tercihine uyuyoruz ve politika her müşteri için aynıdır. Sitenin sahibiyseniz, robots.txt dosyanıza WebReaderAPI için bir kural ekleyin; crawler sayfası bunun nasıl yapıldığını gösterir.
Var olan bir sayfa için neden fetch_failed alıyorum?
Site çökmüş, TLS bağlantısını kabul etmekte yavaş kalmış veya otomatik istemcilere 404 döndürmüş olabilir. Artan bekleme süreleriyle bir ya da iki kez yeniden deneyin. Hata devam ederse adresi bir tarayıcıda kontrol edin.
Bir ret sonrasında ajanım kullanıcıya ne söylemeli?
Basit bir şey, örneğin sitenin o sayfanın otomatik okunmasına izin vermediği. Ardından modelin başka kaynakları kullanmasına izin verin. Hata kodunu araç sonucu olarak döndürmek çoğu model için yeterlidir.