https://txtfetch.com/extract/docx/
Every Office format, one endpoint.
Word, PowerPoint, Excel, RTF, OpenDocument. Per-format libraries and screenshot-reading VLMs both struggle to cover that breadth in one pipeline.
the-problem
Office documents aren't one format. They're a family: .docx and the legacy .doc binary format, .pptx and .ppt, .xlsx and .xls, plus the OpenDocument siblings (.odt/.ods/.odp) and .rtf. A 'parse Office docs' feature usually means five or six separate libraries, each with its own quirks, versioning, and failure modes. Vision-based extractors treat every page as an image. That loses slide speaker notes, spreadsheet formulas, and the structural distinction between a table and a wall of text. Breadth across office formats is exactly where they're weakest.
one-request-solution
txtfetch wraps Apache Tika's Office parsers behind one request. POST any file in the family, or point it at a URL. You get the same { status, extracted_text } response, with slide notes, sheet contents, and body text included.
curl -X POST https://api.txtfetch.com/v1/extract \
-H "Authorization: Bearer $TXTFETCH_KEY" \
-F file=@board-deck.pptximport os
import requests
with open("board-deck.pptx", "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("board-deck.pptx")]);
const form = new FormData();
form.append("file", file, "board-deck.pptx");
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);package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
type extractResponse struct {
Status string `json:"status"`
ExtractedText string `json:"extracted_text"`
}
func main() {
f, err := os.Open("board-deck.pptx")
if err != nil {
panic(err)
}
defer f.Close()
var body bytes.Buffer
writer := multipart.NewWriter(&body)
part, err := writer.CreateFormFile("file", "board-deck.pptx")
if err != nil {
panic(err)
}
if _, err := io.Copy(part, f); err != nil {
panic(err)
}
writer.Close()
req, err := http.NewRequest("POST", "https://api.txtfetch.com/v1/extract", &body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("TXTFETCH_KEY"))
req.Header.Set("Content-Type", writer.FormDataContentType())
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)
}Or skip the download. Pass a url parameter and txtfetch fetches the document server-side:
curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/sales-workbook.xlsx" \
-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/sales-workbook.xlsx"},
)
print(r.json()["extracted_text"])const endpoint = new URL("https://api.txtfetch.com/v1/extract");
endpoint.searchParams.set("url", "https://example.com/sales-workbook.xlsx");
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/sales-workbook.xlsx")
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": "..."
}what-comes-back
That is the shape. This is the text. A real .docx from the benchmark corpus, word-diffed against the raw parser output. Nothing here was written for this page. Every character comes from a committed fixture.
Q3 2026 Board Update (DOCX)
raw parser output
Q3 2026 Board Update
This update covers Q3 2026 performance across all product lines.
Highlights
Annual recurring revenue grew 14% quarter over quarter
Shipped the structured-output beta
Markdown mode
Element JSON mode
Support headcount increased to 6 engineers
Revenue by Plan
Plan MRR Growth
Hobby $0 n/a
Developer $18,200 11%
Scale $41,900 19%
Full detail is available in the appendix & supporting spreadsheets.
the human-checked ideal
Q3 2026 Board Update
This update covers Q3 2026 performance across all product lines.
Highlights
Annual recurring revenue grew 14% quarter over quarter
Shipped the structured-output beta
Markdown mode
Element JSON mode
Support headcount increased to 6 engineers
Revenue by Plan
Plan MRR Growth
Hobby $0 n/a
Developer $18,200 11%
Scale $41,900 19%
Full detail is available in the appendix & supporting spreadsheets.See all ten documents, with the full explanation →
try-your-own
Drop your own .docx file below. Your browser reads it. Nothing uploads, and txtfetch never sees it.
Stays in your browser. Up to 25 MB.
What's not in this text:
Your browser read this file. No request left your browser, so txtfetch never received it. The API returns this same text as { status, extracted_text }.
See the real API response in the playground. Need many files, a folder, or a .zip? Use file-to-text instead.
formats-covered
.docx.doc.pptx.ppt.xlsx.xls.odt.ods.odp.rtf
faq
- How do I extract text from a .docx file?
- POST it as multipart form data to https://api.txtfetch.com/v1/extract with your API key in the Authorization header. The response is { "status": "success", "extracted_text": "..." }.
- Can it read PowerPoint speaker notes, not just slide text?
- Yes. Apache Tika extracts slide body text and speaker notes from .pptx/.ppt files. Both are included in the returned text.
- Do footnotes, comments and headers come back from a .docx?
- Yes. They come back as plain text, in the same response as the body. A comment carries the reviewer's name. See /docs/headers-and-notes for real output.
- Do tracked changes come back from a .docx?
- Yes, deleted words too. Nothing marks them, and moved text comes back twice. Accept all changes before you upload. See /docs/tracked-changes for real output.
- Can it read a password-protected Word or Excel file?
- No. An encrypted .docx or .xlsx fails with extraction_failed and the message tika returned 422. It does not return the encrypted code. A file with only an edit restriction or a protected sheet comes back in full. See /docs/password-protected.
- Does it handle the legacy .doc and .xls binary formats too?
- Yes. txtfetch covers both the modern XML-based Office formats and their legacy binary predecessors through the same endpoint.
- What about OpenDocument files (.odt, .ods, .odp)?
- Supported the same way. POST the file or its URL, and get back the same JSON response shape as any other format.
go-further
- Read the .docx guide →
- Does a table come back as a table? Real output by format →
- Does the text in a picture come back? Real output by format →
- Drop a real .docx and see the exact text it extracts to, free →
- Need the .doc / .xls / .ppt 97-2003 story specifically? →
- Equations in your Word files? They do not come back →
- Forms in your Word files? Their values come back inline →
- Links in your Word files? The addresses do not come back →
- Headers, footnotes and comments in your Word files? They come back inline →
- Tracked changes in your Word files? Deleted words come back →
- Password-protected Word or Excel file? It fails. Unlock it first →
- API quickstart →
- How the pipeline works →
- Extract it from your language →
- Get an API key →
Send a real .docx through it.
One HTTP call returns the text. Read one in your browser first, for free.
Get an API key →