# LangChain dan LlamaIndex: web page loader dan tool read_url

> Web page loader LangChain dan LlamaIndex: tool read_url, document loader, dan indeks RAG kecil dari crawl di Python. Tanpa KYC, bayar dengan kripto.

- URL: https://webreaderapi.com/id/docs/langchain/
- Terakhir diperbarui: 2026-10-22
- Penerbit: WebReaderAPI (https://webreaderapi.com)

Dua cara menggunakan API di stack AI Python: memuat halaman sebagai dokumen untuk retrieval, atau memberi agent sebuah tool `read_url`. 20 baris kode perekat yang sama melayani LangChain dan LlamaIndex.

**Jawaban singkat — Bagaimana cara memuat halaman web ke LangChain atau LlamaIndex sebagai Markdown yang bersih?**

Panggil endpoint `/read` milik **WebReaderAPI** dan bungkus setiap jawaban dalam `Document`: Markdown sebagai content, `final_url` dan title sebagai metadata. Untuk agent, tampilkan panggilan yang sama sebagai tool `read_url`. Setiap halaman berbiaya 1 kredit, 2 kredit dengan browser, mulai dari US$0,07/1K halaman per Oktober 2026. Tidak perlu paket dari kami. Tanpa KYC; bayar dengan kripto.

## Mengapa dokumen Markdown daripada HTML mentah?

Karena retrieval bekerja pada teks, dan Markdown mempertahankan struktur yang penting sambil membuang sisanya. Heading tetap ada, sehingga splitter dapat memotong pada pergantian topik. List dan tabel tetap ada, sehingga langkah-langkah dan spesifikasi tetap menyatu. Navigasi, cookie banner, dan iklan hilang, sehingga tidak mencemari embeddings Anda atau membuang token.

Metadata berasal dari panggilan yang sama: `final_url` sebagai sumber untuk dikutip, `title`, `published_at` dan `language` untuk penyaringan.

*reader.py: helper bersama (simpan di samping kode Anda)*

```python
import os

import requests

API = "https://webreaderapi.com/api/v1/read"
HEADERS = {"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]}


class PageError(Exception):
    pass


def read_page(url, **options):
    resp = requests.get(API, headers=HEADERS, params={"url": url, **options}, timeout=75)
    body = resp.json()
    if resp.status_code != 200:
        raise PageError(body["error"]["code"])
    return body

```

## Bagaimana cara membuat document loader LangChain?

Ubah setiap halaman menjadi `langchain_core.documents.Document`, lalu pisahkan berdasarkan heading dengan `MarkdownHeaderTextSplitter` dari paket `langchain-text-splitters`. Setiap chunk menyimpan jalur heading di metadata-nya, dan Anda menambahkan URL sumber agar setiap jawaban dapat menunjuk kembali ke halamannya.

Halaman yang dilewati, seperti yang ditolak oleh robots.txt, memunculkan `PageError` beserta kodenya; catat di log lalu lanjutkan.

*LangChain: memuat dan memisahkan halaman*

```python
from langchain_core.documents import Document
from langchain_text_splitters import MarkdownHeaderTextSplitter

from reader import PageError, read_page

splitter = MarkdownHeaderTextSplitter(headers_to_split_on=[("#", "h1"), ("##", "h2"), ("###", "h3")])


def load_pages(urls):
    chunks = []
    for url in urls:
        try:
            page = read_page(url)
        except PageError as exc:
            print("skipped", url, exc)
            continue
        for part in splitter.split_text(page["markdown"]):
            part.metadata.update({"source": page["final_url"], "title": page.get("title", "")})
            chunks.append(part)
    return chunks


docs = load_pages(["https://example.com/docs/install", "https://example.com/docs/configure"])
print(len(docs), "chunks", isinstance(docs[0], Document) if docs else "")

```

## Bagaimana cara memberi agent LangChain sebuah tool read_url?

Hiasi sebuah fungsi dengan `@tool` dari `langchain_core.tools`. Docstring menjadi deskripsi tool yang dibaca model, jadi jelaskan apa yang dikembalikan tool dan kapan harus menggunakannya. Kembalikan teks biasa: baris judul, sumber, dan Markdown, dipotong dengan `max_chars` agar sesuai model Anda.

Ikat tool ke model chat apa pun yang mendukung tool calling, atau teruskan ke konstruktor agent Anda. Model kemudian memanggil `read_url` dengan URL dari percakapan atau dari hasil pencarian.

*LangChain: tool read_url*

```python
import os

from langchain.chat_models import init_chat_model
from langchain_core.tools import tool

from reader import PageError, read_page


@tool
def read_url(url: str, max_chars: int = 20000) -> str:
    """Read a public web page and return its main content as Markdown, with its title and source URL."""
    try:
        page = read_page(url, max_chars=max_chars)
    except PageError as exc:
        return "Could not read the page: " + str(exc)
    return "# " + (page.get("title") or url) + "\nSource: " + page["final_url"] + "\n\n" + page["markdown"]


model = init_chat_model(os.environ.get("CHAT_MODEL", "openai:gpt-4.1-mini")).bind_tools([read_url])
reply = model.invoke("Summarise https://example.com/blog/first-post in three bullet points.")
print(reply.tool_calls)

```

## Bagaimana cara melakukan hal yang sama di LlamaIndex?

LlamaIndex menggunakan kelas `Document` miliknya sendiri dengan `text` dan `metadata`, serta `FunctionTool.from_defaults` untuk mengubah fungsi menjadi tool. Helper-nya tetap sama. Bangun indeks dari dokumen dengan `VectorStoreIndex.from_documents`, yang menggunakan embedding model apa pun yang disebutkan di pengaturan LlamaIndex Anda.

*LlamaIndex: mengindeks crawl, dan tool read_url*

```python
import os
import time

import requests
from llama_index.core import Document, VectorStoreIndex
from llama_index.core.tools import FunctionTool

from reader import HEADERS, PageError, read_page


def crawl_pages(start_url, limit=200):
    job = requests.post("https://webreaderapi.com/api/v1/crawl", headers=HEADERS, json={"url": start_url, "limit": limit}, timeout=30).json()
    pages, cursor = [], None
    while True:
        params = {"cursor": cursor} if cursor else {}
        res = requests.get("https://webreaderapi.com/api/v1/jobs/" + job["job_id"], headers=HEADERS, params=params, timeout=30).json()
        pages += [r for r in res["results"] if "error" not in r]
        cursor = res.get("next_cursor")
        if not cursor and res["status"] == "done":
            return pages
        if not cursor:
            time.sleep(5)


pages = crawl_pages("https://docs.example.com/")
docs = [Document(text=p["markdown"], metadata={"source": p["final_url"], "title": p.get("title", "")}) for p in pages]
index = VectorStoreIndex.from_documents(docs)
print(index.as_query_engine().query("How do I install the product?"))


def read_url(url: str, max_chars: int = 20000) -> str:
    """Read a public web page and return its main content as Markdown."""
    try:
        return read_page(url, max_chars=max_chars)["markdown"]
    except PageError as exc:
        return "Could not read the page: " + str(exc)


read_tool = FunctionTool.from_defaults(fn=read_url, name="read_url")
print(os.environ.get("CHAT_MODEL", "set CHAT_MODEL for your agent"), read_tool.metadata.name)

```

## Seberapa besar crawl yang dibutuhkan indeks RAG kecil?

Lebih kecil dari yang Anda duga. Dokumentasi sebuah produk sering kali hanya beberapa ratus halaman, dan crawl dengan `include_paths` diatur ke bagian docs hanya membaca halaman tersebut. Dengan 1 kredit per halaman, situs docs 300 halaman berbiaya sekitar 300 kredit; 10.000 halaman (US$3,75) menyegarkannya berkali-kali.

Lakukan crawl ulang sesuai jadwal yang cocok dengan seberapa sering sumber berubah, dan bandingkan `final_url` serta `word_count` dengan run sebelumnya untuk hanya me-embed ulang halaman yang berubah. Kredit prabayar tidak pernah kedaluwarsa: halaman yang belum digunakan tetap ada di akun Anda sampai Anda memakainya.

## LangChain dan LlamaIndex: pertanyaan umum

### Apakah ada paket WebReaderAPI untuk LangChain atau LlamaIndex?

Tidak. Helper dan tool di halaman ini adalah keseluruhan integrasinya, jadi Anda dapat menyesuaikannya dengan bebas. WebReaderAPI adalah API HTTPS biasa yang dapat dipanggil oleh klien HTTP Python apa pun.

### Versi LangChain mana yang dibutuhkan?

Versi terbaru apa pun yang memiliki `langchain_core`, `langchain-text-splitters` dan `init_chat_model`. Dekorator tool dan kelas `Document` tetap stabil di berbagai rilis terbaru.

### Bagaimana cara menghindari membaca ulang halaman yang tidak berubah?

Simpan `final_url`, `word_count` dan tanggal setiap pembacaan. Baca ulang sesuai jadwal, dan embed ulang sebuah halaman hanya ketika jumlah kata atau hash kontennya berubah. Setiap pembacaan ulang berbiaya satu kredit, jadi pilih ritme yang cocok dengan sumbernya.

### Bagaimana jika beberapa halaman ditolak?

Halaman tersebut memunculkan `PageError` dengan kode seperti `blocked_by_robots`, dan tidak dikenakan biaya. Jika suatu situs menolak permintaan kami, kami mengembalikan jawabannya: kami tidak pernah menyelesaikan CAPTCHA, masuk ke akun, atau mencoba mengatasi blokir atau paywall.

---

WebReaderAPI: WebReaderAPI adalah API pembaca web untuk AI agent yang mengubah halaman web publik apa pun menjadi Markdown bersih, dibayar dengan kripto tanpa unggah identitas. Kredit prabayar mulai dari US$0,07/1K halaman tidak pernah kedaluwarsa, dan robots.txt dihormati. Tanpa KYC — tanpa identitas, tanpa selfie, tanpa dokumen. Bayar dengan kripto.
