KYC不要 — 身分証もセルフィーも書類も不要。暗号資産で支払い:BTC, USDT, USDC, ETH, SOL, LTC
言語: 日本語
APIキーを取得

ドキュメント · エラー

エラー、robots.txtによる拒否、リトライ

各エラーにはHTTPステータス、安定したcode、読み取り可能なmessageがあります。いずれもクレジットを消費しません。再試行する価値のあるものもありますが、サイトからの拒否は最終的なものであり、当社はそれを回避することはありません。

最終更新:

概要

WebReaderAPIのエラーコードの意味と、再試行すべきものはどれですか?

WebReaderAPIエラーは3つのグループに分かれ、いずれも課金されません。リクエストの問題(invalid_url、invalid_api_key、insufficient_credits)はお客様側で修正が必要です。サイトの決定(blocked_by_robots、blocked_by_site_policy、target_refused)は最終的なものです。一時的な障害(fetch_failed、fetch_timeout、concurrency_limit)はバックオフで再試行できます。クレジットは$0.07/1Kページから始まり、KYC不要の暗号資産で支払われます。

APIが返す可能性のあるエラーコードはどれですか?

本文は常に{"error": {"code", "message"}}で、拒否がサイトからのものである場合はtarget_statusが付加されます。

HTTPcode原因再試行しますか?
400invalid_urlhttp または https ではない、長すぎる、またはプライベート・ローカル・クラウドメタデータのアドレスですいいえ: URLを修正してください
400invalid_parameterパラメータの値がリストまたは範囲外ですいいえ: リクエストを修正してください
401invalid_api_keyキーが未設定、誤り、または失効していますいいえ: APIキーを確認してください
402insufficient_credits残高にクレジットが残っていませんクレジットパック購入後
403blocked_by_robotsサイトの robots.txt が、WebReaderAPI またはすべてのロボットに対してこのページを許可していませんいいえ: 確定です
403blocked_by_site_policyサイトが Content-Signal: ai-input=no を宣言していますいいえ: 確定です
422unsupported_content読み取れない種類(動画、アーカイブ)または大きすぎるファイルですいいえ
429concurrency_limit同時に実行中のリクエストが多すぎますはい、バックオフを付けて
502target_refusedサイトが拒否しました: 403、429、チャレンジページ、またはログインウォールです。ステータスは target_status にありますいいえ: 確定です
502fetch_failedDNS、TLS、接続エラー、またはサイトが 404 か 410 を返しました1~2回、バックオフを付けて
504fetch_timeoutサイトが timeout 以内に応答しませんでしたはい、バックオフまたはより長いタイムアウトで

robots.txt とサイトによる拒否が確定なのはなぜですか?

それはサイト所有者の判断であり、WebReaderAPI はそれに従うように作られているからです。当社はrobots.txtを尊重します。クローラーはWebReaderAPIとして名乗り、自身向けまたはすべてのロボット向けに書かれたルールに従い、サイトが禁止したページは読み取りません。拒否されたページは課金されません。サイトがrobots.txtでContent-Signal: ai-input=noを宣言している場合、そのページをあなたのために読み取ることはありません。

サイトが別の形でリクエストを拒否した場合、403、429、チャレンジページ、ログインフォームなどでは、target_refused とサイト自身のステータスが target_status に返ります。サイトが当社のリクエストを拒否した場合、その回答をそのまま返します。CAPTCHAを解いたり、アカウントにログインしたり、ブロックやペイウォールを回避しようとしたりすることは決してありません。同じ URL を1分後に再試行しても通常は同じ結果になるため、これらのコードは失敗ではなく結果として扱ってください。ログに記録して次に進みます。

ページが拒否された理由を確認するには?

サイトの /robots.txt を開き、WebReaderAPI を名指すグループ、またはすべてのロボットに適用される * グループを探してください。パスに一致する Disallow の行があれば blocked_by_robots の説明になります。Content-Signal: ai-input=no のような行は blocked_by_site_policy の説明になります。

robots.txt のコピーは最大24時間保持します。サイトがロボット向けにセクションを開放したばかりの場合、変更が反映されるまで最大1日かかることがあります。サイト所有者は、クローラーの動作と許可・ブロックの方法を クローラーページ で確認できます。

一時的な失敗はどのように再試行すべきですか?

concurrency_limit、fetch_timeout、そして1~2回だけ fetch_failed を再試行してください。新しい試行の前に待機し、待機時間を毎回2倍にし、並列ワーカーが同時に再試行しないよう少しランダムなジッターを加えます。4~5回試行したら停止してください。

concurrency_limit には、一度に送るリクエストを減らすのがより良い対処です: すべてのアカウントには同時に読み取れるページ数の上限があります。上限はダッシュボードに表示され、サポートで引き上げられます。fetch_timeout には、遅いサイトを再試行する前に timeout を最大60秒まで延ばしてください。失敗した試行は課金されないため、再試行に費用はかかりません。

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: 指数バックオフで同じルールを適用
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);
  }
}

バッチやクロール内のエラーはどうなりますか?

1ページの失敗でジョブ全体が止まることはありません。そのページはresults内に{url, error}として、上記と同じコードとともに記録され、クレジットは消費されません。あるセクションでblocked_by_robotsに遭遇したクロールは、単にサイトの残りの部分を読み進めます。

ジョブ終了時にエラーコードを集計します。1つのサイトでtarget_refusedが多い場合は、そのサイトが自動リーダーを受け付けていないことを意味します。fetch_timeoutが多い場合はサイトが遅いことを意味し、ジョブオプションでtimeoutを長くすると改善する場合があります。

エラー: よくある質問

robots.txtでブロックされたページは課金されますか?

いいえ。1クレジット = ブラウザなしでページを1回読み取り。ページのJavaScriptレンダリングにブラウザが必要な場合は2クレジット。失敗したリクエスト、またはサイトのrobots.txtが拒否したリクエストは課金されません。このページに記載されている他のすべてのエラーも同様です。

依頼すれば、クローラーをブロックしているページも読めますか?

いいえ。私たちはサイト所有者の選択に従い、ポリシーはすべてのお客様に同じです。サイトを所有している場合は、robots.txtにWebReaderAPI用のルールを追加してください。方法はクローラーページに記載されています。

存在するページなのにfetch_failedが返るのはなぜですか?

サイトがダウンしていた、TLS接続の受け付けが遅かった、または自動クライアントに対して404を返していた可能性があります。バックオフを入れて1〜2回リトライしてください。それでも失敗し続ける場合は、ブラウザでアドレスを確認してください。

拒否された後、エージェントはユーザーに何と伝えるべきですか?

「このサイトはそのページの自動読み取りを許可していません」といったシンプルな内容で十分です。その後、モデルに他の情報源を使わせてください。エラーコードをツールの結果として返すだけで、ほとんどのモデルには十分です。

$0.07/1Kページから · KYC不要

APIキーを取得