Integrations
URLpipe as a LangChain loader
Rendered pages as LangChain Documents, in about twenty lines you own.
By Roger Campos · Last updated: September 2026
TL;DR
A LangChain document loader for URLpipe is a BaseLoader subclass whose lazy_load posts each URL to https://urlpipe.dev/markdown and yields a Document with the Markdown as page_content and the URL as metadata. It is a recipe you paste into your project, not an official package, and it works with any splitter or vector store.
Free plan, no credit card. 1,000 credits a month.
The idea
Why a custom loader
LangChain's built-in web loaders fetch HTML with a plain HTTP request, or drive a browser you run yourself. URLpipe renders the page in real Chrome on its side and returns Markdown — headings, lists, tables and code blocks kept, navigation and cookie banners dropped — so a MarkdownHeaderTextSplitter has real structure to split on. The conversion uses no model, so the same page gives the same Document every time.
A recipe, not a package
There is no official URLpipe package for LangChain. The class below is about twenty lines you copy into your code and change as you like; it depends only on langchain-core and requests.
Code
The loader
import os
from typing import Iterator
import requests
from langchain_core.document_loaders import BaseLoader
from langchain_core.documents import Document
class URLpipeLoader(BaseLoader):
"""Load web pages as Markdown Documents through URLpipe's /markdown endpoint."""
def __init__(self, urls: list[str], api_key: str | None = None, max_age: str | int = "7 days"):
self.urls = urls
self.max_age = max_age
self.headers = {"Authorization": f"Bearer {api_key or os.environ['URLPIPE_API_KEY']}"}
def lazy_load(self) -> Iterator[Document]:
for url in self.urls:
res = requests.post("https://urlpipe.dev/markdown", headers=self.headers, timeout=75,
json={"url": url, "sync": True, "max_age": self.max_age})
res.raise_for_status()
yield Document(page_content=res.text,
metadata={"source": url, "cache": res.headers.get("X-Cache")})load(), lazy_load() and load_and_split() all work, because BaseLoader builds them on lazy_load.
Code
Using it
from langchain_text_splitters import MarkdownHeaderTextSplitter
docs = URLpipeLoader([
"https://docs.example.com/getting-started",
"https://docs.example.com/api/authentication",
]).load()
splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=[("#", "h1"), ("##", "h2"), ("###", "h3")]
)
chunks = [
chunk
for doc in docs
for chunk in splitter.split_text(doc.page_content)
]
# add doc.metadata["source"] to each chunk's metadata, then hand them to your vector storeFor titles and publication dates in your metadata, post to /scrape with "operations": ["markdown", "meta"] and read operations.markdown.result and operations.meta.result from the JSON — 6 credits a page instead of 1.
Scale
Things to change for production
- Slow pages. A sync call waits up to 60 seconds and then answers
504with a token. Catch it and collect the result fromGET /result/:token, as the agent recipe does. - Parallelism. Your plan runs a fixed number of requests at once — the
X-Concurrency-Limitheader says how many — so a thread pool of that size is the fastest safe loader. More returns429. - Big batches. For thousands of pages, send them async with
report_toand build Documents in the webhook — see RAG ingestion. - Freshness. Re-loading inside
max_ageis a free cache hit; passmax_age=0to force a fresh fetch.
Endpoints
The endpoints on this page
- Turn any URL into clean Markdown
Paste a link and get the page's main content as tidy Markdown — headings, lists, links and code kept, navigation and cookie banners stripped. The format LLMs and RAG pipelines work best with.
Try it free - Everything about a URL, from one visit
Paste a link and get a screenshot of the page, its title, description and share image, the main content as Markdown and the console errors it threw — all from the same page load.
Try it free
FAQ
Frequently asked questions
Is there an official URLpipe LangChain integration?
Does the loader handle JavaScript-rendered pages?
What does each Document cost?
Can I use the loader with async LangChain code?
Connect it in five minutes.
Free plan, no card. Confirm your email and your API key is live — you'll be making real requests in minutes.