https://txtfetch.com/migrate/llamaparse/
Migrate from LlamaParse to txtfetch
Credit-metered tiers and a job to poll, for parsing you may not need. Here's what your code looks like before and after.
Where you are today
The call below is the current llama-cloud Parsing API, checked against LlamaParse's current docs.
import os
from llama_cloud import LlamaCloud
client = LlamaCloud(api_key=os.environ["LLAMA_CLOUD_API_KEY"])
file = client.files.create(file="report.pdf", purpose="parse")
result = client.parsing.parse(
file_id=file.id,
tier="agentic",
version="latest",
expand=["markdown"],
)
text = result.markdown.pages[0].markdownChecked against LlamaParse's docs on 2026-09-10, using llama-cloud 2.16.0.
the call that replaces it
One HTTP call. No SDK to install, and no job to poll.
curl -X POST https://api.txtfetch.com/v1/extract \
-H "Authorization: Bearer $TXTFETCH_KEY" \
-F file=@report.pdfimport os
import requests
with open("report.pdf", "rb") as f:
r = requests.post(
"https://api.txtfetch.com/v1/extract",
headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"},
files={"file": f},
)
print(r.json()["extracted_text"])import { readFile } from "node:fs/promises";
const file = new Blob([await readFile("report.pdf")]);
const form = new FormData();
form.append("file", file, "report.pdf");
const res = await fetch("https://api.txtfetch.com/v1/extract", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` },
body: form,
});
const { extracted_text } = await res.json();
console.log(extracted_text);drop-in adapter
A short function standing in for result.markdown.pages[n].markdown. Change one function, not your whole pipeline.
import os
import requests
def parse_like_pages(file_path: str) -> list[str]:
"""Drop-in swap for result.markdown.pages[n].markdown.
txtfetch has no per-page split, so this returns a one-item list.
Downstream code that joins all pages into one string keeps working
unmodified; code that indexes a specific page needs a rewrite.
"""
with open(file_path, "rb") as f:
r = requests.post(
"https://api.txtfetch.com/v1/extract",
headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"},
files={"file": f},
)
r.raise_for_status()
return [r.json()["extracted_text"]]import { readFile } from "node:fs/promises";
// Drop-in swap for result.markdown.pages[n].markdown. txtfetch has no
// per-page split, so this returns a one-item array.
async function parseLikePages(filePath) {
const file = new Blob([await readFile(filePath)]);
const form = new FormData();
form.append("file", file, filePath);
const res = await fetch("https://api.txtfetch.com/v1/extract", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` },
body: form,
});
const { extracted_text } = await res.json();
return [extracted_text];
}field mapping
| LlamaParse field | txtfetch equivalent | Note |
|---|---|---|
| result.markdown.pages[n].markdown | extracted_text (?format=markdown) | Ask for markdown output to keep heading and list structure. LlamaParse splits by page; txtfetch does not. |
| result.items (per-element JSON) | ?format=json element list | txtfetch's element JSON is coarser than LlamaParse's agentic-tier item breakdown. |
| tier (fast / cost_effective / agentic / agentic_plus) | not applicable | txtfetch runs one extraction path. There is no fidelity dial to set per request. |
| take_screenshot=True (page images) | not returned | txtfetch returns text only, never a page image. |
what you lose
- The agentic and agentic-plus tiers' fidelity on multi-column layouts, embedded tables, and math notation.
- Per-page screenshots and structured item JSON.
- A pinnable parser version for reproducible output across runs.
- output_tables_as_HTML and other tier-specific output options.
See the full capability table on txtfetch vs LlamaParse.
what you gain
- Hundreds of formats through one endpoint (see /formats/coverage), not a PDF-first parser.
- One flat call, no credits to track and no job tier to pick per request.
- Billing per document, not per credit. See the pricing math.
The pricing math behind per-document billing lives on why per-page pricing punishes long documents.
Cutover
Run both calls on the same PDF while you switch over. Diff the two outputs, or clean up formatting differences first on the pages where LlamaParse's fidelity mattered most.
- Compare outputs side by side, to dual-run both calls on the same file.
- Clean up extracted text, if the two outputs disagree on formatting.
frequently asked questions
- Do I need the agentic tier's fidelity, or is plain text enough?
- Depends on the document. If your pipeline only ever reads plain text out of LlamaParse's markdown, txtfetch is a straight swap. If it reads structured items or table HTML, keep LlamaParse for those files.
- Does txtfetch support LlamaParse's parsing tiers?
- No. txtfetch runs one extraction path per document. There is no fast/agentic/agentic_plus tier to choose.
- What happened to the llama-cloud-services package?
- LlamaIndex deprecated it in favor of llama-cloud. The snippet above uses the current package, checked against LlamaIndex's own docs.
Swap the call. Keep the pipeline.
Point your LlamaParse code at txtfetch, then diff the output before you cut over.
Get an API key →