undoc
High-performance Microsoft Office document extraction to Markdown.
Installation
pip install undoc
Usage
Basic Usage
from undoc import parse_file
# Parse a document
doc = parse_file("document.docx")
# Convert to Markdown
markdown = doc.to_markdown()
print(markdown)
# Convert to plain text
text = doc.to_text()
# Convert to JSON
json_data = doc.to_json()
With Context Manager
from undoc import parse_file
with parse_file("document.xlsx") as doc:
print(doc.to_markdown(frontmatter=True))
print(f"Sections: {doc.section_count}")
print(f"Resources: {doc.resource_count}")
Parse from Bytes
from undoc import parse_bytes
with open("document.pptx", "rb") as f:
data = f.read()
doc = parse_bytes(data)
markdown = doc.to_markdown()
Extract Resources (Images)
from undoc import parse_file
doc = parse_file("document.docx")
# Get all resource IDs
resource_ids = doc.get_resource_ids()
for rid in resource_ids:
# Get resource metadata
info = doc.get_resource_info(rid)
# "primary": an image the document shows. "alternate" (a picture's SVG original) and
# "layer" (an HD Photo effects layer) belong to the primary named by companion_of.
if info["role"] != "primary":
continue
print(f"Resource: {info['filename']} ({info['mime_type']})")
# Get resource binary data
data = doc.get_resource_data(rid)
# Save to file
with open(info['filename'], 'wb') as f:
f.write(data)
Document Metadata
from undoc import parse_file
doc = parse_file("document.docx")
print(f"Title: {doc.title}")
print(f"Author: {doc.author}")
print(f"Sections: {doc.section_count}")
print(f"Resources: {doc.resource_count}")
Handling Failures
UndocError.kind says why a call failed, so you can react to the reason instead of
matching on message text:
from undoc import ErrorKind, UndocError, parse_file
try:
doc = parse_file(path)
print(doc.to_markdown())
except UndocError as err:
if err.kind is ErrorKind.ZIP_ARCHIVE:
print("The file is damaged.")
elif err.kind in (ErrorKind.UNKNOWN_FORMAT, ErrorKind.UNSUPPORTED_FORMAT):
print("Not a supported Office document.")
elif err.kind is ErrorKind.ENCRYPTED:
print("The document is encrypted.")
else:
# Also the right branch for a reason this build has no name for.
print(f"Extraction failed ({err.kind}): {err}")
The numbers behind ErrorKind are a stable ABI contract: a new reason takes the next free
number and existing ones are never renumbered. Always keep a final else — an
unrecognised value arrives as a plain int rather than an ErrorKind, so that a newer
native library stays usable. kind is ErrorKind.OTHER for failures raised by the wrapper
itself, and never ErrorKind.NONE (which means success).
Supported Formats
- DOCX - Microsoft Word documents
- XLSX - Microsoft Excel spreadsheets
- PPTX - Microsoft PowerPoint presentations
Features
- RAG-Ready Output: Structured Markdown optimized for RAG/LLM applications
- High Performance: Native Rust implementation via FFI
- Asset Extraction: Images and embedded resources
- Metadata Preservation: Document properties, styles, formatting
- Cross-Platform: Windows, Linux, macOS (Intel & ARM)
API Reference
Functions
parse_file(path)- Parse document from file pathparse_bytes(data)- Parse document from bytesversion()- Get library version
Undoc Class
Conversion Methods
to_markdown(frontmatter=False, escape_special=False, paragraph_spacing=False)- Convert to Markdownto_text()- Convert to plain textto_json(compact=False)- Convert to JSONplain_text()- Get plain text (fast extraction)
Properties
title- Document titleauthor- Document authorsection_count- Number of sectionsresource_count- Number of resources
Resource Methods
get_resource_ids()- List of resource IDsget_resource_info(id)- Resource metadataget_resource_data(id)- Resource binary data
Native library
The package ships the native library for your platform. To load another build of it — one
you compiled from the Rust crate, say — set UNDOC_LIB_PATH to that file. A path that names no file
is an error: importing raises OSError naming the path, rather than quietly loading the
packaged library instead.
License
MIT License - see LICENSE for details.
Metadata
Release files for undoc 0.17.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| undoc-0.17.0.tar.gz | 5.8 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| undoc-0.17.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.6 MB
Release files / undoc-0.17.0.tar.gz
| Download URL | undoc-0.17.0.tar.gz |
|---|---|
| Size | 5.8 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
31db4b91c6c618f38bf5f6d1153f54dcd4eca20573341653c5ba8ce6a889e7e3
|
|
BLAKE2b-256 checksum How to use checksums |
768664b6d30be2d9a3f4e3730d0fe4db4e8c2bf825678327e37b9cb80d7d7752
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / undoc-0.17.0-py3-none-any.whl
| Download URL | undoc-0.17.0-py3-none-any.whl |
|---|---|
| Size | 5.8 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b68b3422d2b5074172506d27011754cd3b5e5abd666c990540fead3cad6b5f9b
|
|
BLAKE2b-256 checksum How to use checksums |
a4927d4d0676d28a58d99c7d228e9d0eb2ca2ee548a6263b42d25c79e477e591
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|