# รูปแบบการตอบกลับของ Read API ทีละฟิลด์

> รูปแบบการตอบกลับของ Read API: ทุกฟิลด์ที่ส่งคืนสำหรับหน้า จาก markdown และ word_count ถึง final_url และ rendered พร้อมผลลัพธ์ของ job ไม่ต้อง KYC จ่ายด้วยคริปโต

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

การเรียก `/read` ทุกครั้งส่งคืน JSON object หนึ่งรายการ: เนื้อหาของหน้าในรูปแบบที่คุณขอ metadata ของมัน และสามฟิลด์ที่บอกคุณว่าเกิดอะไรขึ้นและมีค่าใช้จ่ายเท่าใด ผลลัพธ์ของ job ใช้ object เดียวกัน

**คำตอบสั้น — การตอบกลับของ WebReaderAPI read ประกอบด้วยอะไร?**

การตอบกลับ **WebReaderAPI** `/read` ประกอบด้วยเนื้อหาของหน้าใน `markdown` (หรือ `text` หรือ `html`) metadata ของมัน (`title`, `description`, `author`, `published_at`, `language`, `site_name`, `word_count`) และข้อเท็จจริงของการดึงข้อมูล: `final_url`, `status_code`, `rendered` และ `credits_used` หน้าเว็บธรรมดาใช้ 1 เครดิต จาก US$0.07/1K หน้า ณ เดือนตุลาคม 2026 ไม่ต้อง KYC จ่ายด้วยคริปโต

## ฟิลด์ใดอธิบายการดึงข้อมูล?

ฟิลด์เหล่านี้มีอยู่เสมอในการตอบกลับที่สำเร็จ

| ฟิลด์ | ประเภท | ความหมาย |
| --- | --- | --- |
| `url` | string | ที่อยู่ที่คุณส่งไป |
| `final_url` | string | ที่อยู่ที่อ่านจริง หลัง redirect (สูงสุด 5 ครั้ง) |
| `status_code` | integer | สถานะ HTTP ที่เว็บไซต์ส่งกลับสำหรับที่อยู่สุดท้าย ปกติคือ 200 |
| `fetched_at` | string | เวลาที่ดึงข้อมูล รูปแบบ ISO 8601 ใน UTC |
| `rendered` | boolean | `true` เมื่อเบราว์เซอร์แบบ headless สร้างหน้าเว็บ |
| `credits_used` | integer | เครดิตที่เรียกเก็บสำหรับหน้านี้: 1, 2 เมื่อใช้เบราว์เซอร์ และเพิ่ม 10 เมื่อใช้ `country`; PDF คิด 1 เครดิตต่อทุก 10 หน้าที่เริ่มอ่าน |

## ฟิลด์ใดอธิบายหน้าเว็บ?

Metadata มาจากตัวหน้าเว็บเอง: title tag, meta tag, structured data และชื่อผู้เขียนที่มองเห็น ฟิลด์ที่หน้าเว็บไม่ได้ให้มาจะไม่ปรากฏ ดังนั้นควรตรวจสอบก่อนใช้งาน

| ฟิลด์ | ประเภท | ความหมาย |
| --- | --- | --- |
| `title` | string | ชื่อหน้าเว็บหรือชื่อบทความ |
| `description` | string | บทสรุปที่หน้าเว็บให้เกี่ยวกับตัวเอง |
| `language` | string | รหัสภาษาของเนื้อหา เช่น `en` หรือ `de` |
| `author` | string | ชื่อผู้เขียนที่ระบุบนหน้าเว็บ |
| `published_at` | string | วันที่เผยแพร่ที่ระบุโดยหน้าเว็บ |
| `site_name` | string | ชื่อของเว็บไซต์เอง |
| `word_count` | integer | จำนวนคำในเนื้อหาที่ส่งกลับ หลังการดึงเนื้อหาหลักและก่อน `max_chars` |

## เนื้อหาอยู่ที่ใด?

มีฟิลด์เนื้อหาหนึ่งฟิลด์ที่ส่งกลับ โดยตั้งชื่อตาม `format` ที่คุณเลือก

| ฟิลด์ | เมื่อ | เนื้อหา |
| --- | --- | --- |
| `markdown` | `format=markdown` (ค่าเริ่มต้น) | หัวข้อ ย่อหน้า รายการ ตาราง และลิงก์ใน Markdown รวมถึงรูปภาพด้วยเมื่อใช้ `include_images=true` |
| `text` | `format=text` | ข้อความล้วน ย่อหน้าคั่นด้วยบรรทัดว่าง |
| `html` | `format=html` | HTML ที่ผ่านการทำความสะอาดของเนื้อหาหลัก โดยไม่มี script, style หรือโฆษณา |
| `links` | `include_links=true` | รายการ`{url, text}`สำหรับลิงก์ที่พบบนหน้าเว็บ เป็น URL แบบ absolute |

*ตัวอย่างการตอบกลับที่สมบูรณ์ (ค่าต่างๆ เป็นเพียงตัวอย่าง)*

```json
{
  "url": "https://example.com/guides/compost",
  "final_url": "https://example.com/guides/compost-at-home",
  "status_code": 200,
  "fetched_at": "2026-10-22T10:02:44Z",
  "rendered": false,
  "credits_used": 1,
  "title": "Compost at home: a beginner's guide",
  "description": "What to put in a compost bin, and what to leave out.",
  "language": "en",
  "author": "Sam Rivera",
  "published_at": "2026-09-14",
  "site_name": "Example Garden",
  "markdown": "# Compost at home: a beginner's guide\n\nA compost bin turns kitchen scraps into soil...\n\n## What goes in\n\n- Fruit and vegetable peels\n- Coffee grounds\n\nSee also [Choosing a bin](https://example.com/guides/bins).",
  "word_count": 1184,
  "links": [
    { "url": "https://example.com/guides/bins", "text": "Choosing a bin" }
  ]
}
```

## จะแยกหน้าเว็บที่เรนเดอร์แล้วออกจากหน้าเว็บธรรมดาได้อย่างไร?

ดูที่ `rendered` ด้วย `render=auto` API จะอ่าน HTML ดิบก่อน และจะเริ่มเบราว์เซอร์ก็ต่อเมื่อ HTML นั้นมีข้อความน้อยเกินไป จากนั้นจึงตั้งค่า `rendered` เป็น `true` และ `credits_used` เป็น 2 ถ้าเว็บไซต์ที่คุณอ่านบ่อยมักส่งกลับมาเป็นหน้าเรนเดอร์เสมอ ให้ส่ง `render=true` ตั้งแต่แรก: ค่าใช้จ่ายเท่าเดิมและข้ามขั้นตอนแรกที่ไม่จำเป็นได้

ถ้าหน้ากลับมาแบบไม่เรนเดอร์แต่เนื้อหาน้อย ให้เทียบ `word_count` กับสิ่งที่คุณเห็นในเบราว์เซอร์ จำนวนที่ต่ำมักหมายความว่าเนื้อหาต้องใช้ JavaScript; ลองอีกครั้งด้วย `render=true`

## ทำไม final_url ถึงต่างจาก url?

เพราะเว็บไซต์มีการ redirect ลิงก์สั้น ที่อยู่เก่า เครื่องหมายทับท้ายที่หายไป หรือการสลับภาษา ล้วนพาคุณไปที่อื่น API จะติดตาม redirect สูงสุด 5 ครั้ง และรายงานที่อยู่ที่อ่านได้ในที่สุดใน `final_url`

เก็บ `final_url` เป็นแหล่งอ้างอิงหลัก (canonical) ของเอกสารใน RAG index ค่า `url` ที่ต่างกันแต่ลงเอยที่ `final_url` เดียวกันคือหน้าเดียวกัน ดังนั้นคุณสามารถตัดตัวซ้ำออกก่อนฝัง (embed) ได้

## ผลลัพธ์ของงาน (job) มีหน้าตาอย่างไร?

`GET https://webreaderapi.com/api/v1/jobs/{job_id}` ส่งกลับ `job_id`, `status` (`queued`, `running` หรือ `done`), `results`, `next_cursor` และ `credits_used` ที่กำลังทำงานของงานนั้น แต่ละรายการใน `results` มีได้หนึ่งในสองรูปแบบ:

- การตอบกลับแบบ `/read` เต็มรูปแบบ ตามที่อธิบายไว้ข้างต้น สำหรับหน้าที่ถูกอ่านแล้ว;
- `{url, error}` สำหรับหน้าที่ไม่ได้ถูกอ่าน โดยที่ `error` มี `code` และ `message` เดียวกับ [API error](https://webreaderapi.com/th/docs/errors/)

`next_cursor` จะมีอยู่เมื่อยังมีผลลัพธ์เพิ่มเติมพร้อมแล้ว; ส่งกลับมาเป็น `cursor` เพื่อรับผลเหล่านั้น [หน้าสำหรับ batch และ crawl](https://webreaderapi.com/th/docs/crawl/) มีลูปการ polling ที่สมบูรณ์

*หน้าผลลัพธ์ของงาน (ค่าต่างๆ เป็นเพียงตัวอย่าง)*

```json
{
  "job_id": "job_5c1e8a90d2",
  "status": "done",
  "results": [
    { "url": "https://example.com/blog/post-1", "final_url": "https://example.com/blog/post-1", "status_code": 200, "rendered": false, "credits_used": 1, "title": "Post one", "markdown": "# Post one\n\n...", "word_count": 802 },
    { "url": "https://example.org/members/area", "error": { "code": "target_refused", "message": "The site refused the request.", "target_status": 403 } }
  ],
  "credits_used": 1
}
```

## การตอบกลับข้อผิดพลาดมีหน้าตาอย่างไร?

ข้อผิดพลาดจะส่งกลับมาพร้อมสถานะ HTTP 400 ขึ้นไปและ body เป็น JSON `{"error": {"code", "message"}}` เมื่อเว็บไซต์เองปฏิเสธคำขอ `target_status` จะแสดงสถานะที่เว็บไซต์ส่งมา ไม่มีการเรียกเก็บเงินเมื่อเกิดข้อผิดพลาด [หน้าข้อผิดพลาด](https://webreaderapi.com/th/docs/errors/) แสดงรายการทุกโค้ดพร้อมสาเหตุและบอกว่าการลองใหม่จะช่วยได้หรือไม่

## รูปแบบการตอบกลับ: คำถามที่พบบ่อย

### Markdown ถูกตัดเมื่อตั้งค่า max_chars หรือไม่?

ใช่ ฟิลด์ content จะหยุดที่จำนวนอักขระนั้น `word_count` ยังคงอธิบายเนื้อหาที่ดึงมาทั้งหมด所以你ยังเห็นได้ว่าถูกตัดออกไปเท่าไร

### ทำไม author หรือ published_at ถึงหายไป?

เพราะหน้าเว็บไม่ได้ระบุไว้ในรูปแบบที่อ่านได้ หลายหน้าไม่มีชื่อผู้เขียนหรือวันที่ ฟิลด์ที่ไม่มีจะถูกตัดออกแทนที่จะส่งกลับมาแบบว่างเปล่า

### ลิงก์ใน Markdown เป็น absolute หรือไม่?

ลิงก์ในรายการ `links` เป็น absolute เขียนโค้ดให้รองรับทั้งสองรูปแบบในเนื้อหา Markdown และแปลงลิงก์แบบ relative โดยอ้างอิงกับ `final_url`

### ขอ raw HTML ของทั้งหน้าเว็บได้ไหม?

สิ่งที่ใกล้เคียงที่สุดคือ `format=html` พร้อม `main_content=false` ซึ่งส่งกลับทั้งหน้าที่ถูกทำความสะอาด scripts และ styles แล้ว HTML ต้นฉบับแบบ byte-for-byte ไม่มีใน v1

---

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