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

> WebReaderAPIのすべてのエラーコード：robots.txtによる拒否、サイトによる拒否、タイムアウト、クレジットエラー、再試行すべきもの、およびそれらのいずれも課金されない理由。

- URL: https://webreaderapi.com/ja/docs/errors/
- 最終更新: 2026-10-22
- 発行者: WebReaderAPI (https://webreaderapi.com)

各エラーには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`が付加されます。

| HTTP | `code` | 原因 | 再試行しますか？ |
| --- | --- | --- | --- |
| 400 | `invalid_url` | http または https ではない、長すぎる、またはプライベート・ローカル・クラウドメタデータのアドレスです | いいえ: URLを修正してください |
| 400 | `invalid_parameter` | パラメータの値がリストまたは範囲外です | いいえ: リクエストを修正してください |
| 401 | `invalid_api_key` | キーが未設定、誤り、または失効しています | いいえ: APIキーを確認してください |
| 402 | `insufficient_credits` | 残高にクレジットが残っていません | クレジットパック購入後 |
| 403 | `blocked_by_robots` | サイトの robots.txt が、WebReaderAPI またはすべてのロボットに対してこのページを許可していません | いいえ: 確定です |
| 403 | `blocked_by_site_policy` | サイトが `Content-Signal: ai-input=no` を宣言しています | いいえ: 確定です |
| 422 | `unsupported_content` | 読み取れない種類（動画、アーカイブ）または大きすぎるファイルです | いいえ |
| 429 | `concurrency_limit` | 同時に実行中のリクエストが多すぎます | はい、バックオフを付けて |
| 502 | `target_refused` | サイトが拒否しました: 403、429、チャレンジページ、またはログインウォールです。ステータスは `target_status` にあります | いいえ: 確定です |
| 502 | `fetch_failed` | DNS、TLS、接続エラー、またはサイトが 404 か 410 を返しました | 1～2回、バックオフを付けて |
| 504 | `fetch_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日かかることがあります。サイト所有者は、クローラーの動作と許可・ブロックの方法を [クローラーページ](https://webreaderapi.com/ja/bot/) で確認できます。

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

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

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

*Python: 変わりうるエラーだけを再試行する*

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

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

```

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

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

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

## エラー: よくある質問

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

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

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

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

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

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

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

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

---

WebReaderAPI: WebReaderAPIはAIエージェント向けのWebリーダーAPIで、あらゆる公開WebページをクリーンなMarkdownに変換します。暗号資産で支払い、本人確認書類のアップロードは不要です。$0.07/1Kページから購入できるプリペイドクレジットに有効期限はなく、robots.txtを尊重します。KYC不要 — 身分証もセルフィーも書類も不要。暗号資産で支払い。
