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.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 | |
|---|---|---|---|
| unhwp-0.13.0.tar.gz | 8.3 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unhwp-0.13.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.6 MB
Release files / unhwp-0.13.0.tar.gz
| Download URL | unhwp-0.13.0.tar.gz |
|---|---|
| Size | 8.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a7a175485e2d01a0b5f417a770e832fcf8c91c57d1b4bc95888baebd8f67b310
|
|
BLAKE2b-256 checksum How to use checksums |
967b1b478eb7e2ce6f7e5f931e79bd3b91aa1c5d2ba98e1783a785a9dcdc382d
|
| 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.0-py3-none-any.whl
| Download URL | unhwp-0.13.0-py3-none-any.whl |
|---|---|
| Size | 8.3 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7c4232614017d165dda6fbe3d5f4f90713212f1d0906d3f5e564875ab8ba7a55
|
|
BLAKE2b-256 checksum How to use checksums |
d389a57b9457b7d3063fff6eeaa2b6ce8c292b2386c9532fec4c77392d8432fc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|