https://txtfetch.com/migrate/azure-document-intelligence/
Migrate from Azure AI Document Intelligence to txtfetch
The prebuilt-read model, minus the SDK, the poller, and the Azure resource. Here's what your code looks like before and after.
Where you are today
The call below is prebuilt-read, checked against Azure AI Document Intelligence's current docs.
import os
from azure.ai.documentintelligence import DocumentIntelligenceClient
from azure.core.credentials import AzureKeyCredential
client = DocumentIntelligenceClient(
endpoint=os.environ["DOCUMENTINTELLIGENCE_ENDPOINT"],
credential=AzureKeyCredential(os.environ["DOCUMENTINTELLIGENCE_API_KEY"]),
)
with open("report.pdf", "rb") as f:
poller = client.begin_analyze_document("prebuilt-read", body=f)
result = poller.result()
text = result.contentChecked against Azure AI Document Intelligence's docs on 2026-09-10, using azure-ai-documentintelligence 1.0.2.
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.content. Change one function, not your whole pipeline.
import os
import requests
def analyze_like_result(file_path: str) -> str:
"""Drop-in swap for poller.result().content.
Downstream code that reads result.content as one string keeps working
unmodified. Code that reads result.pages or result.paragraphs needs a
rewrite. txtfetch returns no per-page or per-paragraph split.
"""
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 poller.result().content. Downstream code that reads
// result.content as one string keeps working unmodified.
async function analyzeLikeResult(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
| Azure AI Document Intelligence field | txtfetch equivalent | Note |
|---|---|---|
| result.content | extracted_text | Both are one plain-text string for the whole document. This is the closest field pair in this whole cluster. |
| result.pages[].lines[].content | not split out | txtfetch's response carries no per-page or per-line breakdown. |
| result.words[].confidence | not returned | No per-word confidence score comes back. |
| prebuilt-invoice / prebuilt-receipt typed fields | not returned | txtfetch has no prebuilt document-type models. Keep Document Intelligence for typed field extraction. |
what you lose
- Prebuilt models for invoices, receipts, IDs, and W-2s that return named fields.
- Bounding regions (polygons) per line, word, and paragraph.
- Per-word confidence scores.
- prebuilt-layout's table extraction with row and column indices.
See the full capability table on txtfetch vs Azure AI Document Intelligence.
what you gain
- Hundreds of formats through one endpoint (see /formats/coverage), not PDF, images, and a limited set of Office formats.
- One HTTP call. No Azure resource, no SDK, no poller to await.
- Billing per document, not per 1,000 pages. 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 file while you switch traffic over. Diff the two outputs, since result.content and extracted_text usually match closely for plain text extraction.
- 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
- Is result.content close enough to txtfetch's extracted_text to swap directly?
- For plain text, usually yes. Both return one string for the whole document. Run the diff tool on a real file before you cut over.
- Does txtfetch support Document Intelligence's prebuilt invoice or receipt models?
- No. Those return typed fields. txtfetch returns plain text only. Keep Document Intelligence for that part of your pipeline.
- Do I need result.pages or result.paragraphs, or just the full text?
- If your code only reads result.content, this is a direct swap. If it reads per-page or per-paragraph structure, that structure has no txtfetch equivalent.
Swap the call. Keep the pipeline.
Point your Azure AI Document Intelligence code at txtfetch, then diff the output before you cut over.
Get an API key →