unhwp
High-performance Python library for extracting HWP/HWPX Korean word processor documents to Markdown.
Installation
pip install unhwp
Quick Start
import unhwp
# Simple conversion
markdown = unhwp.to_markdown("document.hwp")
print(markdown)
# Extract plain text
text = unhwp.extract_text("document.hwp")
# Full parsing with images
with unhwp.parse("document.hwp") as result:
print(result.markdown)
print(f"Sections: {result.section_count}")
print(f"Paragraphs: {result.paragraph_count}")
# Save images
for img in result.images:
img.save(f"output/{img.name}")
Handling Failures
UnhwpError.kind says why a call failed, so you can react to the reason instead of
matching on message text:
from unhwp import ErrorKind, ParseError
try:
with unhwp.parse(path) as result:
print(result.markdown)
except ParseError as err:
if err.kind in (ErrorKind.OLE_CONTAINER, ErrorKind.ZIP_ARCHIVE):
print("The file is damaged.")
elif err.kind in (ErrorKind.UNKNOWN_FORMAT, ErrorKind.UNSUPPORTED_FORMAT):
print("Not a supported HWP/HWPX document.")
elif err.kind in (ErrorKind.ENCRYPTED, ErrorKind.DISTRIBUTION_RESTRICTED):
print("The document cannot be opened without authorization.")
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).
Features
- Fast: Native Rust library with zero-copy parsing
- Complete: Extracts text, tables, images, and document structure
- Clean Output: Optional cleanup pipeline for polished Markdown
- Format Support: HWP 5.0, HWPX, and HWP 3.x (legacy)
API Reference
Functions
to_markdown(path) -> str
Convert an HWP/HWPX document to Markdown.
markdown = unhwp.to_markdown("document.hwp")
to_markdown_with_cleanup(path, cleanup_options=None) -> str
Convert with optional cleanup.
markdown = unhwp.to_markdown_with_cleanup(
"document.hwp",
cleanup_options=unhwp.CleanupOptions.aggressive()
)
extract_text(path) -> str
Extract plain text content.
text = unhwp.extract_text("document.hwp")
parse(path, render_options=None) -> ParseResult
Parse a document with full access to content and images.
with unhwp.parse("document.hwp") as result:
print(result.markdown)
print(result.text)
for img in result.images:
print(img.name, len(img.data))
detect_format(path) -> int
Detect the document format.
fmt = unhwp.detect_format("document.hwp")
if fmt == unhwp.FORMAT_HWP5:
print("HWP 5.0 format")
elif fmt == unhwp.FORMAT_HWPX:
print("HWPX format")
Classes
RenderOptions
Options for Markdown rendering.
opts = unhwp.RenderOptions(
include_frontmatter=True,
image_path_prefix="images/",
preserve_line_breaks=False,
)
CleanupOptions
Options for output cleanup.
# Presets
opts = unhwp.CleanupOptions.minimal()
opts = unhwp.CleanupOptions.default()
opts = unhwp.CleanupOptions.aggressive()
opts = unhwp.CleanupOptions.disabled()
# Custom
opts = unhwp.CleanupOptions(
enabled=True,
preset=1,
detect_mojibake=True,
)
Constants
FORMAT_UNKNOWN- Unknown formatFORMAT_HWP5- HWP 5.0 binary formatFORMAT_HWPX- HWPX XML formatFORMAT_HWP3- HWP 3.x legacy format
Platform Support
- Windows (x64)
- Linux (x64)
- macOS (x64, ARM64)
License
MIT License - see LICENSE for details.
Links
Metadata
Release files for unhwp 0.13.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| unhwp-0.13.2.tar.gz | 8.3 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unhwp-0.13.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.6 MB
Release files / unhwp-0.13.2.tar.gz
| Download URL | unhwp-0.13.2.tar.gz |
|---|---|
| Size | 8.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c408706c1dba3573b2f81fa160ac052bd225804d6b91e55dbe5eb9eec1804dcf
|
|
BLAKE2b-256 checksum How to use checksums |
21c0dbd21052407c12f26a319dc79590e9ffad6c8f5b0f839c280835d1ecba8b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / unhwp-0.13.2-py3-none-any.whl
| Download URL | unhwp-0.13.2-py3-none-any.whl |
|---|---|
| Size | 8.3 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a28f4b47139eb02983dd5a18ada4bca4fa944f23f8f0eb3192247474d3082668
|
|
BLAKE2b-256 checksum How to use checksums |
0eb48616df9b5b73f2cb7c8258f8d0f0a64663da8f44fb862137cbec129ae25f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|