# Định dạng phản hồi API Read, từng trường một

> API Read trả về mọi trường cho một trang, từ markdown và word_count đến final_url và rendered, cùng với kết quả job. Không cần KYC, thanh toán bằng crypto.

- URL: https://webreaderapi.com/vi/docs/response/
- Cập nhật lần cuối: 2026-10-22
- Đơn vị phát hành: WebReaderAPI (https://webreaderapi.com)

Mỗi lệnh gọi `/read` trả về một đối tượng JSON: nội dung của trang ở định dạng bạn yêu cầu, metadata của nó, và ba trường cho bạn biết điều gì đã xảy ra và chi phí bao nhiêu. Kết quả job dùng lại cùng đối tượng đó.

**Câu trả lời nhanh — Phản hồi read của WebReaderAPI chứa gì?**

Một phản hồi **WebReaderAPI** `/read` chứa nội dung trang trong `markdown` (hoặc `text` hoặc `html`), metadata của nó (`title`, `description`, `author`, `published_at`, `language`, `site_name`, `word_count`), và các thông tin của lần tải: `final_url`, `status_code`, `rendered` và `credits_used`. Một trang thông thường tốn 1 credit, từ 0,07 US$/1K trang tính đến tháng 10 năm 2026. Không cần KYC; thanh toán bằng crypto.

## Trường nào mô tả lần tải?

Các trường này luôn có mặt trong một phản hồi thành công.

| Field | Kiểu | Ý nghĩa |
| --- | --- | --- |
| `url` | string | Địa chỉ bạn đã gửi |
| `final_url` | string | Địa chỉ thực sự được đọc, sau các redirect (tối đa 5) |
| `status_code` | số nguyên | Mã trạng thái HTTP mà trang trả về cho địa chỉ cuối cùng, thường là 200 |
| `fetched_at` | string | Thời điểm fetch, ISO 8601 theo UTC |
| `rendered` | boolean | `true` khi trình duyệt headless dựng trang |
| `credits_used` | số nguyên | Số credit bị tính cho trang này: 1, 2 nếu dùng trình duyệt, cộng thêm 10 nếu dùng `country`; PDF tính 1 credit cho mỗi 10 trang đã bắt đầu |

## Những field nào mô tả trang?

Metadata lấy từ chính trang: thẻ title, các thẻ meta, dữ liệu có cấu trúc và byline hiển thị. Field nào trang không cung cấp thì sẽ vắng mặt, nên hãy kiểm tra trước khi dùng.

| Field | Kiểu | Ý nghĩa |
| --- | --- | --- |
| `title` | string | Tiêu đề của trang hoặc bài viết |
| `description` | string | Phần tóm tắt mà trang tự đưa ra về chính nó |
| `language` | string | Mã ngôn ngữ của nội dung, ví dụ `en` hoặc `de` |
| `author` | string | Tác giả được nêu trên trang |
| `published_at` | string | Ngày xuất bản do trang nêu |
| `site_name` | string | Tên của chính trang web |
| `word_count` | số nguyên | Số từ trong nội dung trả về, sau khi trích xuất và trước `max_chars` |

## Nội dung nằm ở đâu?

Một field nội dung được trả về, đặt tên theo `format` bạn đã chọn.

| Field | Khi nào | Nội dung |
| --- | --- | --- |
| `markdown` | `format=markdown` (mặc định) | Tiêu đề, đoạn văn, danh sách, bảng và liên kết ở dạng Markdown; cả hình ảnh nếu dùng `include_images=true` |
| `text` | `format=text` | Văn bản thuần, các đoạn cách nhau bằng dòng trống |
| `html` | `format=html` | HTML đã làm sạch của nội dung chính, không có script, style hay quảng cáo |
| `links` | `include_links=true` | Danh sách `{url, text}` cho các liên kết tìm thấy trên trang, dưới dạng URL tuyệt đối |

*Một phản hồi hoàn chỉnh (các giá trị chỉ mang tính minh họa)*

```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" }
  ]
}
```

## Làm sao để phân biệt một trang đã render với một trang thường?

Hãy xem `rendered`. Với `render=auto`, API trước tiên đọc HTML thô; nó chỉ khởi động trình duyệt khi HTML đó chứa quá ít văn bản, và khi đó đặt `rendered` thành `true` và `credits_used` thành 2. Nếu một trang web bạn đọc thường xuyên luôn trả về ở dạng đã render, hãy gửi `render=true` ngay từ đầu: chi phí như nhau và bạn bỏ qua một bước đầu tiên không cần thiết.

Nếu một trang trả về không render nhưng ít nội dung, hãy so sánh `word_count` với những gì bạn thấy trên trình duyệt. Số đếm thấp thường có nghĩa là nội dung cần JavaScript; hãy thử lại một lần với `render=true`.

## Tại sao final_url có thể khác với url?

Vì các trang web chuyển hướng. Một liên kết rút gọn, một địa chỉ cũ, thiếu dấu gạch chéo cuối hoặc một lần chuyển đổi ngôn ngữ đều đưa bạn sang nơi khác. API theo tối đa 5 lần chuyển hướng và báo cáo địa chỉ mà nó thực sự đã đọc trong `final_url`.

Hãy lưu `final_url` làm nguồn chuẩn tắc của một tài liệu trong chỉ mục RAG. Hai giá trị `url` khác nhau mà kết thúc tại cùng một `final_url` chính là cùng một trang, nên bạn có thể loại bỏ bản trùng trước khi nhúng nó.

## Kết quả của một job trông như thế nào?

`GET https://webreaderapi.com/api/v1/jobs/{job_id}` trả về `job_id`, `status` (`queued`, `running` hoặc `done`), `results`, `next_cursor` và `credits_used` đang chạy của job. Mỗi mục của `results` thuộc một trong hai dạng:

- một phản hồi `/read` đầy đủ, đúng như mô tả ở trên, cho một trang đã được đọc;
- `{url, error}` cho một trang chưa được đọc, trong đó `error` có cùng `code` và `message` như một [lỗi API](https://webreaderapi.com/vi/docs/errors/).

`next_cursor` xuất hiện khi còn kết quả sẵn sàng; hãy gửi lại nó dưới dạng `cursor` để lấy các kết quả đó. [Trang batch và crawl](https://webreaderapi.com/vi/docs/crawl/) có một vòng lặp polling hoàn chỉnh.

*Một trang kết quả của job (các giá trị chỉ mang tính minh họa)*

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

## Một phản hồi lỗi trông như thế nào?

Lỗi trả về với HTTP status từ 400 trở lên và một JSON body `{"error": {"code", "message"}}`. Khi chính trang web từ chối yêu cầu, `target_status` cho biết status mà trang web đã gửi. Không có lỗi nào bị tính phí. [Trang lỗi](https://webreaderapi.com/vi/docs/errors/) liệt kê mọi mã lỗi cùng nguyên nhân và liệu thử lại có ích hay không.

## Định dạng phản hồi: các câu hỏi thường gặp

### Markdown có bị cắt khi tôi đặt max_chars không?

Có. Trường content dừng ở đúng số ký tự đó. `word_count` vẫn mô tả toàn bộ nội dung đã trích xuất, nên bạn có thể thấy đã bỏ sót bao nhiêu.

### Tại sao author hoặc published_at bị thiếu?

Vì trang không nêu thông tin đó theo cách có thể đọc được. Nhiều trang không cung cấp tác giả hay ngày tháng. Các trường vắng mặt sẽ bị lược bỏ chứ không trả về rỗng.

### Các liên kết trong Markdown có phải URL tuyệt đối không?

Các liên kết trong danh sách `links` là tuyệt đối. Hãy viết code của bạn để chấp nhận cả hai dạng trong phần thân Markdown, và phân giải các liên kết tương đối dựa trên `final_url`.

### Tôi có thể lấy HTML thô của toàn bộ trang không?

Cách gần nhất là `format=html` với `main_content=false`, trả về toàn bộ trang đã được làm sạch khỏi script và style. HTML gốc từng byte không nằm trong v1.

---

WebReaderAPI: WebReaderAPI là web reader API cho AI agent, chuyển mọi trang web công khai thành Markdown sạch, thanh toán bằng crypto không cần tải lên giấy tờ. Credit trả trước từ 0,07 US$/1K trang không bao giờ hết hạn, và robots.txt được tôn trọng. Không cần KYC — không ID, không selfie, không giấy tờ. Thanh toán bằng crypto.
