https://txtfetch.com/solutions/search-indexing/
Every file in your document estate, made searchable.
Contracts, decks, spreadsheets, and scanned forms all land in the same folder. One extraction call turns each into indexable plain text.
the-problem
A search index is only as complete as the pipeline that feeds it. Document estates are never one format. A shared drive holds PDFs, Word docs, Excel exports, and scanned paperwork someone photographed on a phone. Teams often build separate handling for each format. Files outside that set never reach the index, and they become a blind spot.
how-txtfetch-solves-it
txtfetch gives every file type the same code path. POST it, or point at its URL, and get back plain text. Hand that text to your indexer's bulk API: Elasticsearch, OpenSearch, Algolia, or Meilisearch. Scanned pages route through OCR automatically. A folder of PDFs, Office files, and photographed forms indexes through one loop instead of three.
- One extraction call covers every source format, so no per-format indexer feed is needed.
- OCR runs automatically on scanned and photographed documents, in the same request shape as any other format.
- Pass a URL to index a linked or attached document without a separate download step.
- Async job mode with a webhook callback indexes large batches without holding a connection open.
- Idempotency-Key support stops a retried indexing job from double-indexing a document.
- The response text drops straight into Elasticsearch, OpenSearch, Algolia, or Meilisearch.
- The response is plain JSON, easy to script into a nightly re-index job.
curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/report.docx" \
-H "Authorization: Bearer $TXTFETCH_KEY"import os
import requests
r = requests.post(
"https://api.txtfetch.com/v1/extract",
headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"},
params={"url": "https://example.com/report.docx"},
)
print(r.json()["extracted_text"])const endpoint = new URL("https://api.txtfetch.com/v1/extract");
endpoint.searchParams.set("url", "https://example.com/report.docx");
const res = await fetch(endpoint, {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` },
});
const { extracted_text } = await res.json();
console.log(extracted_text);package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
)
type extractResponse struct {
Status string `json:"status"`
ExtractedText string `json:"extracted_text"`
}
func main() {
endpoint, err := url.Parse("https://api.txtfetch.com/v1/extract")
if err != nil {
panic(err)
}
q := endpoint.Query()
q.Set("url", "https://example.com/report.docx")
endpoint.RawQuery = q.Encode()
req, err := http.NewRequest("POST", endpoint.String(), nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("TXTFETCH_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result extractResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
panic(err)
}
fmt.Println(result.ExtractedText)
}{
"status": "success",
"extracted_text": "..."
}faq
- Can txtfetch feed an Elasticsearch or OpenSearch index?
- Yes. POST each document, or its URL, to /v1/extract. Hand the returned extracted_text to your indexer's bulk API. txtfetch doesn't talk to the index directly; it just gives you clean text to index.
- What happens to scanned documents in a search-indexing pipeline?
- They're OCR'd automatically via Tesseract, same request and response shape as a digital-native file, so scanned paperwork ends up searchable alongside everything else.
- How do I index a large batch without blocking on slow OCR jobs?
- Pass async=true, or use the SDK's extractAsync/extract_async. Poll the job, or supply a webhook_url. The batch submits right away, and results arrive as they complete.
related-reading
Start on the free plan.
Run your own documents through it before you commit. The Hobby plan needs no card.
Get started →