> Source: https://txtfetch.com/extract/docx > Plain-text twin — every page on txtfetch.com has one. https://txtfetch.com/text --- # 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 ```curl curl -X POST https://api.txtfetch.com/v1/extract \ -H "Authorization: Bearer $TXTFETCH_KEY" \ -F file=@board-deck.pptx ``` Python ```python import 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"]) ``` JavaScript ```javascript 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); ``` Go ```go 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 ```curl curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/sales-workbook.xlsx" \ -H "Authorization: Bearer $TXTFETCH_KEY" ``` Python ```python 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"]) ``` JavaScript ```javascript 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); ``` Go ```go 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) `board-update-q3-2026.docx` · application/vnd.openxmlformats-officedocument.wordprocessingml.document · left pane read via Apache Tika, **right pane: the human-checked expected.json** 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 →](https://txtfetch.com/diff) 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. **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 →](https://txtfetch.com/blog/parse-office-docs-docx-pptx-xlsx-for-llms) - [Drop a real .docx and see the exact text it extracts to, free →](https://txtfetch.com/tools/docx-to-text) - [Need the .doc / .xls / .ppt 97-2003 story specifically? →](https://txtfetch.com/extract/legacy-office) - [API quickstart →](https://txtfetch.com/docs) - [How the pipeline works →](https://txtfetch.com/how-it-works) - [Extract it from your language →](https://txtfetch.com/for) - [Get an API key →](https://app.txtfetch.com/signup) Office - [`.pptx`](https://txtfetch.com/extract/pptx) - [`.xlsx`](https://txtfetch.com/extract/xlsx) - [`.doc`](https://txtfetch.com/extract/legacy-office) - [`.rtf`](https://txtfetch.com/extract/rtf) - [All formats →](https://txtfetch.com/extract) ## Send a real .docx through it. One HTTP call returns the text. Read one in your browser first, for free. [Get an API key →](https://app.txtfetch.com/signup) [Open the free .docx reader →](https://txtfetch.com/tools/docx-to-text)