OpenDocKit
Turn any document into clean, LLM-ready Markdown.
PDF · DOCX · PPTX · XLSX · HWP/HWPX · HTML · email · CSV · images — one function, no GPU, MIT licensed.
from opendockit import convert_file
result = convert_file("quarterly-report.hwp")
result.text # Markdown: headings, tables, lists, footnotes, LaTeX equations
result.sections # per page / slide / sheet — for chunking and citations ("page 3")
result.warnings # what was skipped or approximated, in plain sentences
Why OpenDocKit
Most converters handle the happy path. OpenDocKit is built for the files people actually upload.
- Structure, not just text. Merged table cells, multi-column PDFs, borderless tables, nested lists, footnotes, speaker notes, native charts as data tables, SmartArt as nested lists, Word / PowerPoint / Hancom equations as LaTeX.
- First-class Korean documents. A from-scratch HWP 5.x parser, HWPX, CP949 detection, NFC normalization, and the form-heavy tables Korean offices produce. Most general-purpose converters cannot read these at all.
- Detects by content, not extension. An HTML table saved as
.xls, a CSV with a title block, an MHTML page named.doc— each is read as what it really is, and a warning tells you. - Safe on untrusted uploads. Zip bombs, runaway merged-cell counts, recursive PDF objects and multi-gigabyte images
are bounded.
IsolatedConverterruns every file in a disposable worker process with memory and time limits. - Images in place. Pictures, charts and scanned pages are extracted, filtered, and — if you plug in a vision model — described right where they appeared in the document.
- A hard character budget.
max_charsstops work instead of truncating afterwards, so a file that will be rejected anyway costs neither parsing time nor vision-model calls. - Permissive by default. MIT licensed; everything a plain
pip install opendockitbrings in is MIT / BSD / Apache-style (no PyMuPDF, no pyhwp), with no ML models and no GPU. The only copyleft code is behind the opt-inheicextra.
Installation
pip install opendockit # conversion only — never touches the network
pip install "opendockit[openai]" # + image description with a vision model
pip install "opendockit[heic]" # + HEIC/HEIF images (pulls in GPL/LGPL-licensed codec libraries)
Requires Python 3.12 or newer on Linux or macOS. Windows is not supported yet for HTML and email (why).
Quick start
Convert
from opendockit import convert, convert_file
result = convert_file("report.pdf") # from a path
result = convert(data, "report.pdf") # from bytes (the filename is only a hint)
print(result.text)
print(result.char_count, result.exceeded) # size of the output, and whether the limit stopped it
convert is synchronous, offline and deterministic. Pictures are collected in result.images and the text keeps an
[Image] placeholder where each one was.
Describe images with a vision model
from opendockit import OpenAIImageDescriber, aconvert
result = await aconvert(data, "report.pdf", describer=OpenAIImageDescriber()) # reads OPENAI_API_KEY
Charts become data tables, diagrams become lists, scanned pages are transcribed, and decorative images are dropped.
OpenAIImageDescriber(model) accepts any LangChain chat model, and anything with an
async describe(image) -> str method works as a describer. See docs/images.md.
Serve it
from opendockit import ConversionError, IsolatedConverter
async with IsolatedConverter(workers=2) as converter: # 2 GB and 2 minutes per file by default
try:
result = await converter.convert(data, filename)
except ConversionError as exc:
print(exc.code, exc) # stable code + a message safe to show users
One bad file ends one worker; your server and the next upload carry on. See docs/server.md.
Command line
opendockit report.pdf # Markdown on stdout, warnings on stderr
opendockit report.pdf --json # sections, metadata, warnings, images
opendockit report.pdf --count # just the character count
opendockit scan.pdf --describe # describe images with a vision model (uses OPENAI_API_KEY)
Supported formats
| Format | Sections | Highlights |
|---|---|---|
| page | reading order across columns, ruled and borderless tables, form field values, headings from font size, repeated header/footer removal, scanned pages via vision model | |
| DOCX | document | heading styles, list numbering, merged cells, charts → tables, SmartArt, footnotes/endnotes, equations → LaTeX, comments |
| PPTX | slide | on-screen order, bullet levels, tables, charts → tables, SmartArt, equations, speaker notes |
| XLSX · XLS · Excel 2003 XML · CSV | sheet | several tables per sheet, merged cells, number and date formats, charts, cell comments |
| HWP · HWPX | document | outline headings, numbering, merged cells, captions, footnotes, equations → LaTeX |
| HTML · MHTML | document | tables with rowspan/colspan, layout tables unwrapped, MathML → LaTeX, hidden elements removed |
Email (.eml, mbox) |
document | headers, HTML or plain body, forwarded messages, calendar invites |
| TXT · Markdown | document | encoding detection (UTF-8, CP949, UTF-16, Windows-1252) |
| Images | document / page | JPEG, PNG, WebP, GIF, BMP, TIFF, AVIF, and HEIC with the heic extra — described by a vision model |
Not supported: legacy .doc/.ppt, RTF, ODF. The full list of what each format restores is in
docs/formats.md; the honest list of what it cannot do is in docs/limitations.md.
Examples
examples/ has one sample document per format and the Markdown OpenDocKit produces from each — with and
without a vision model — so you can judge the output before installing anything.
Documentation
| Formats | What is extracted from each format and how it is rendered |
| Options | ConvertOptions, exceptions and error codes |
| Images | Extraction, filtering, vision models, custom describers |
| Running on a server | IsolatedConverter, resource limits, the character budget |
| Integration guide | What an upload UI should tell its users |
| Design | Why it is built this way, and how it was verified |
| Limitations | Known gaps, stated plainly |
| Decision records | Every deliberate trade-off, with the test that pins it |
Contributing
Contributions are welcome — bug reports with a minimal reproducing document are especially valuable. Start with CONTRIBUTING.md.
git clone https://github.com/hyeonsang010716/OpenDocKit.git && cd OpenDocKit
uv sync
uv run pytest -n auto -m "not timing" # the bulk of the suite, in parallel
uv run pytest -m timing # tests that measure time, one at a time
uv run ruff check
License
Metadata
Release files for opendockit 0.1.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 | Provenance | Actions |
|---|---|---|---|---|
| opendockit-0.1.0.tar.gz | 1.2 MB | With provenance | Details for opendockit-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| opendockit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for opendockit-0.1.0-py3-none-any.whl |
Total release size: 1.7 MB
Release files / opendockit-0.1.0.tar.gz
| Download URL | opendockit-0.1.0.tar.gz |
|---|---|
| Size | 1.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c3397af4aefafe2b0c36dc0eed9d822da06dec604f0f4dcf1f45b4f62d1d3f0f
|
|
BLAKE2b-256 checksum How to use checksums |
6ad3815f03fd9ad3e8eb25101c9245acb96f157d87bc900374d0c69d36a3db64
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logRelease files / opendockit-0.1.0-py3-none-any.whl
| Download URL | opendockit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 518.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
96623cf9c6c8774c37d568285117290775a562ee8f6e9ba6ea7d252d5e1ecd50
|
|
BLAKE2b-256 checksum How to use checksums |
8f7a530c6ef8b546bcdf4bd417cf407ab6f61b15ca9e953d1aaa69e5fb579d15
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logSecurity for opendockit 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for opendockit-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.