# Errors, robots.txt และ Retries

> error code ทั้งหมดของ WebReaderAPI: การปฏิเสธจาก robots.txt, การปฏิเสธจากไซต์, timeout และ credit errors, ตัวไหนควรลองใหม่ และทำไมไม่มีการคิดเงินเลย

- URL: https://webreaderapi.com/th/docs/errors/
- อัปเดตล่าสุด: 2026-10-22
- ผู้เผยแพร่: WebReaderAPI (https://webreaderapi.com)

แต่ละ error มี HTTP status, `code` ที่เสถียร และ `message` ที่อ่านได้ ไม่มีตัวไหนใช้เครดิต บางตัวควรลองใหม่; การปฏิเสธที่มาจากไซต์ถือเป็นที่สุด และเราไม่เคยหลีกเลี่ยงมัน

**คำตอบสั้น — error code ของ WebReaderAPI หมายถึงอะไร และตัวไหนควรลองใหม่?**

error ของ **WebReaderAPI** แบ่งเป็นสามกลุ่ม และไม่มีการคิดเงินเลย ปัญหาคำขอ (`invalid_url`, `invalid_api_key`, `insufficient_credits`) ต้องแก้ฝั่งคุณ การตัดสินใจของไซต์ (`blocked_by_robots`, `blocked_by_site_policy`, `target_refused`) ถือเป็นที่สุด ความล้มเหลวชั่วคราว (`fetch_failed`, `fetch_timeout`, `concurrency_limit`) ลองใหม่ได้ด้วย backoff เครดิตเริ่มที่ US$0.07/1K หน้า จ่ายด้วยคริปโตโดยไม่ต้อง KYC

## API สามารถคืน error code อะไรได้บ้าง?

body เป็น `{"error": {"code", "message"}}` เสมอ บวก `target_status` เมื่อการปฏิเสธมาจากไซต์

| HTTP | `code` | สาเหตุ | ลองอีกครั้งหรือไม่? |
| --- | --- | --- | --- |
| 400 | `invalid_url` | ไม่ใช่ http หรือ https, ยาวเกินไป, หรือเป็นที่อยู่ส่วนตัว, ภายในเครื่อง หรือ cloud metadata | ไม่: แก้ URL |
| 400 | `invalid_parameter` | พารามิเตอร์มีค่านอกช่วงหรือนอกตัวเลือกที่อนุญาต | ไม่: แก้คำขอ |
| 401 | `invalid_api_key` | API key หายไป ผิด หรือถูกเพิกถอน | ไม่: ตรวจสอบ API key |
| 402 | `insufficient_credits` | ยอดคงเหลือของคุณไม่มีเครดิตเหลือแล้ว | หลังซื้อแพ็ก |
| 403 | `blocked_by_robots` | robots.txt ของเว็บไซต์ไม่อนุญาตหน้านี้สำหรับ WebReaderAPI หรือสำหรับ robots ทั้งหมด | ไม่: เป็นการสิ้นสุด |
| 403 | `blocked_by_site_policy` | เว็บไซต์ประกาศ `Content-Signal: ai-input=no` | ไม่: เป็นการสิ้นสุด |
| 422 | `unsupported_content` | ประเภทไฟล์ที่เราไม่รองรับ (วิดีโอ, ไฟล์บีบอัด) หรือไฟล์ใหญ่เกินไป | ไม่ใช่ |
| 429 | `concurrency_limit` | คำขอของคุณทำงานพร้อมกันมากเกินไป | ได้ พร้อม backoff |
| 502 | `target_refused` | เว็บไซต์ปฏิเสธ: 403, 429, หน้า challenge หรือหน้า login; สถานะอยู่ใน `target_status` | ไม่: เป็นการสิ้นสุด |
| 502 | `fetch_failed` | เกิดข้อผิดพลาด DNS, TLS หรือการเชื่อมต่อ หรือเว็บไซต์ตอบ 404 หรือ 410 | หนึ่งหรือสองครั้ง พร้อม backoff |
| 504 | `fetch_timeout` | เว็บไซต์ไม่ตอบกลับภายใน `timeout` | ได้ พร้อม backoff หรือเพิ่ม timeout |

## ทำไม robots.txt และการที่เว็บไซต์ปฏิเสธจึงถือเป็นข้อยุติ?

เพราะนั่นคือการตัดสินใจของเจ้าของเว็บไซต์ และ WebReaderAPI ถูกสร้างมาให้ปฏิบัติตามนั้น เราเคารพ robots.txt: crawler ของเราระบุตัวเองว่า WebReaderAPI ทำตามกฎที่เขียนไว้สำหรับมันหรือสำหรับ robot ทั้งหมด และจะไม่อ่านหน้าที่เว็บไซต์ไม่อนุญาต หน้าที่ถูกปฏิเสธจะไม่ถูกคิดเครดิต หากเว็บไซต์ประกาศ Content-Signal: ai-input=no ใน robots.txt ของมัน เราจะไม่อ่านหน้าของเว็บนั้นให้คุณ

เมื่อเว็บไซต์ปฏิเสธคำขอในรูปแบบอื่น เช่น 403, 429, หน้า challenge หรือฟอร์ม login คุณจะได้รับ `target_refused` พร้อมสถานะจากเว็บไซต์เองใน `target_status` หากเว็บไซต์ปฏิเสธคำขอของเรา เราจะส่งคำตอบของเว็บนั้นกลับไป: เราไม่แก้ CAPTCHA ไม่เข้าสู่ระบบบัญชี และไม่พยายามหลบเลี่ยงการบล็อกหรือ paywall การลอง URL เดิมอีกครั้งในอีกหนึ่งนาทีมักได้คำตอบเดิม ดังนั้นให้ถือว่าโค้ดเหล่านี้เป็นผลลัพธ์ ไม่ใช่ความล้มเหลว: บันทึกไว้แล้วไปต่อ

## ฉันจะตรวจสอบได้อย่างไรว่าทำไมหน้าเว็บจึงถูกปฏิเสธ?

เปิด `/robots.txt` ของเว็บไซต์ แล้วมองหากลุ่มที่ระบุ `WebReaderAPI` หรือกลุ่ม `*` ที่ใช้กับ robots ทั้งหมด บรรทัด `Disallow` ที่ตรงกับ path อธิบาย `blocked_by_robots` บรรทัดอย่าง `Content-Signal: ai-input=no` อธิบาย `blocked_by_site_policy`

เราเก็บสำเนา robots.txt แต่ละไฟล์ไว้ไม่เกิน 24 ชั่วโมง หากเว็บไซต์เพิ่งเปิดส่วนหนึ่งให้ robots การเปลี่ยนแปลงอาจใช้เวลาถึงหนึ่งวันจึงจะมีผล เจ้าของเว็บไซต์สามารถอ่านว่า crawler ของเราทำงานอย่างไร และวิธีอนุญาตหรือบล็อกได้ที่ [หน้าข้อมูล crawler ของเรา](https://webreaderapi.com/th/bot/)

## ฉันควรลองใหม่เมื่อเกิดความล้มเหลวชั่วคราวอย่างไร?

ให้ลองใหม่เฉพาะ `concurrency_limit`, `fetch_timeout` และ `fetch_failed` หนึ่งหรือสองครั้ง รอก่อนการลองแต่ละครั้งและเพิ่มเวลาเป็นสองเท่าทุกครั้ง พร้อม jitter แบบสุ่มเล็กน้อยเพื่อไม่ให้ worker ที่ทำงานขนานกันลองใหม่พร้อมกัน หยุดหลังลอง 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: กฎเดียวกันพร้อม exponential 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);
  }
}

```

## แล้วข้อผิดพลาดภายใน batch หรือ crawl ล่ะ?

งานจะไม่หยุดเพราะหน้าใดหน้าหนึ่งล้มเหลว หน้านั้นจะปรากฏใน `results` เป็น `{url, error}` พร้อมรหัสเดียวกับด้านบน และไม่เสียเครดิต การ crawl ที่เจอ `blocked_by_robots` ในบางส่วนของเว็บก็แค่อ่านส่วนที่เหลือของเว็บต่อ

เมื่อจบงาน ให้นับรหัสข้อผิดพลาด `target_refused` จำนวนมากบนเว็บหนึ่งแห่งหมายความว่าเว็บนั้นไม่รับตัวอ่านอัตโนมัติ `fetch_timeout` จำนวนมากหมายความว่าเว็บช้า และการตั้ง `timeout` ที่นานขึ้นในตัวเลือกของงานอาจช่วยได้

## ข้อผิดพลาด: คำถามที่พบบ่อย

### ฉันถูกเรียกเก็บเงินสำหรับหน้าที่ robots.txt บล็อกหรือไม่?

ไม่ 1 เครดิต = อ่าน 1 หน้าโดยไม่ใช้เบราว์เซอร์; 2 เครดิตเมื่อหน้านั้นต้องใช้เบราว์เซอร์เพื่อเรนเดอร์ JavaScript คำขอที่ล้มเหลว หรือที่ robots.txt ของเว็บไซต์ปฏิเสธ จะไม่ถูกคิดเครดิต เช่นเดียวกับข้อผิดพลาดอื่น ๆ ทั้งหมดในหน้านี้

### ถ้าฉันขอ คุณอ่านหน้าที่บล็อก crawler ของคุณได้ไหม?

ไม่ได้ เราทำตามการตัดสินใจของเจ้าของเว็บ และนโยบายเดียวกันสำหรับลูกค้าทุกคน ถ้าคุณเป็นเจ้าของเว็บ ให้เพิ่มกฎสำหรับ `WebReaderAPI` ใน robots.txt ของคุณ [หน้า crawler](https://webreaderapi.com/th/bot/) แสดงวิธีทำ

### ทำไมฉันจึงได้ fetch_failed สำหรับหน้าที่มีอยู่จริง?

เว็บอาจล่ม ช้าในการตอบรับการเชื่อมต่อ TLS หรือตอบ 404 ให้กับไคลเอนต์อัตโนมัติ ลองใหม่อีกหนึ่งหรือสองครั้งแบบ backoff ถ้ายังล้มเหลว ให้ตรวจสอบที่อยู่ในเบราว์เซอร์

### เอเจนต์ของฉันควรบอกผู้ใช้อย่างไรหลังการปฏิเสธ?

บอกง่าย ๆ เช่น เว็บนั้นไม่อนุญาตให้อ่านหน้านั้นโดยอัตโนมัติ จากนั้นให้โมเดลใช้แหล่งอื่น การคืนรหัสข้อผิดพลาดเป็นผลลัพธ์ของ tool ก็เพียงพอสำหรับโมเดลส่วนใหญ่

---

WebReaderAPI: WebReaderAPI คือ API อ่านหน้าเว็บสำหรับ AI agent ที่แปลงหน้าเว็บสาธารณะใด ๆ เป็น Markdown สะอาด จ่ายด้วยคริปโตโดยไม่ต้องอัปโหลดบัตรประชาชน เครดิตแบบเติมเงินเริ่มต้นที่ US$0.07/1K หน้า ไม่มีวันหมดอายุ และเคารพ robots.txt ไม่ต้อง KYC — ไม่ต้องใช้บัตรประชาชน ไม่ต้องเซลฟี่ ไม่ต้องเอกสาร จ่ายด้วยคริปโต
