Reader board

Which Python library reads PDF, Word, Excel and PowerPoint files without breaking? Which OCR engine reads images best, and which speech-to-text engine makes the fewest mistakes? Document libraries run on the same odd real-world files from the test collections of pdf.js, Apache POI and Apache Tika (bug reports, fuzzers, broken exporters); OCR and speech engines on images and audio with known text. Every new release on PyPI is tested again by itself.

Updated 06 November 2026. Lower is better in the ๐Ÿ”ด ๐ŸŸก โฑ columns; the table is sorted by them (the any-document table: by files turned into text). Click a library to see every file it failed on, with the error, and what changed between its versions. New releases as they are tested: Atom feed.

๐Ÿ† Best per format

PDFPyMuPDFfails on 6 of 724 readable filesWord (.docx)docx2txtfails on 1 of 103 readable filesExcel (.xlsx)python-calaminefails on 2 of 297 readable filesPowerPoint (.pptx)markitdownfails on 0 of 66 readable filesAny document โ†’ textKreuzbergtext from 374 of 477 filesOCR (image โ†’ text)PaddleOCRfinds 95.1% of the wordsSpeech to text (English)Parakeetword error rate 11.1%Language detectionpy3langid97.0% correct

PDF

1,077 files from Mozilla pdf.js test PDFs; 724 of them give text to at least one library.
Library๐Ÿ”ด Fails where
another reads
๐ŸŸก Empty where
another reads
โฑ Hangs or
crashes
Text from
(all files)
Errors
(all files)
Median
ms/file
Total
seconds
1 PyMuPDF 2.167071114213.2
2 pypdfium2 5.15.0655066324110.0
3 pypdf 7.0.0
since 6.21.4: โ–ผ 1 newly failing
11490664344145.8
4 pdfminer.six 20260107
since 20251230: โ–ฒ 2 fixed
11640649314179.5
5 pdfplumber 0.11.10
since 0.11.9: โ–ฒ 1 fixed
11640649325227.6
6 markitdown 0.1.9
since 0.1.8: โ–ผ 1 newly failing
126416483194516.3

Word (.docx)

130 files from Apache POI test files; 103 of them give text to at least one library.
Library๐Ÿ”ด Fails where
another reads
๐ŸŸก Empty where
another reads
โฑ Hangs or
crashes
Text from
(all files)
Errors
(all files)
Median
ms/file
Total
seconds
1 docx2txt 0.91001021612.9
2 mammoth 1.13.02709417914.9
3 python-docx 1.2.02130881734.3
4 markitdown 0.1.9370931817497.3

Excel (.xlsx)

353 files from Apache POI test files; 297 of them give text to at least one library.
Library๐Ÿ”ด Fails where
another reads
๐ŸŸก Empty where
another reads
โฑ Hangs or
crashes
Text from
(all files)
Errors
(all files)
Median
ms/file
Total
seconds
1 python-calamine 0.9.122029326<12.0
2 openpyxl 3.1.556028628619.4
3 markitdown 0.1.9110228632111315.1

PowerPoint (.pptx)

95 files from Apache POI test files; 66 of them give text to at least one library.
Library๐Ÿ”ด Fails where
another reads
๐ŸŸก Empty where
another reads
โฑ Hangs or
crashes
Text from
(all files)
Errors
(all files)
Median
ms/file
Total
seconds
1 markitdown 0.1.900066127112.9
2 python-pptx 1.0.20110551292.7

Any document โ†’ text

477 files from Apache Tika test documents; 406 of them give text to at least one library.
Library๐Ÿ”ด Fails where
another reads
๐ŸŸก Empty where
another reads
โฑ Hangs or
crashes
Text from
(all files)
Errors
(all files)
Format not
supported
Median
ms/file
Total
seconds
1 Kreuzberg 4.10.411190374304<18.7
2 Unstructured 0.27.368220370281130507.4
3 Docling 2.148.01041266231507580.7
4 markitdown 0.1.9417125318149125388.2

By file type: files read with text

TypeKreuzbergUnstructuredDoclingmarkitdown
.docx 71 files60/71 7 empty 4 failed57/71 10 empty 3 failed 1 not supported59/71 6 empty 6 failed57/71 10 empty 4 failed
.pdf 71 files45/71 22 empty 4 failed50/71 16 empty 5 failed52/71 14 empty 5 failed44/71 21 empty 6 failed
.doc 49 files37/49 5 empty 7 failed37/49 9 empty 1 failed 2 not supportednot supportednot supported
.rtf 44 files41/44 3 empty40/44 2 empty 2 failednot supportednot supported
.html 38 files34/38 2 empty 2 failed34/38 2 empty 2 failed36/38 2 empty36/38 2 empty
.xlsx 35 files22/35 9 empty 4 failed21/35 10 empty 4 failed20/35 8 empty 7 failed20/35 9 empty 6 failed
.txt 30 files30/3030/3028/30 2 failed30/30
.xls 30 files18/30 8 empty 4 failed18/30 7 empty 5 failednot supported20/30 8 empty 2 failed
.pptx 29 files22/29 6 empty 1 failed21/29 7 empty 1 failed23/29 5 empty 1 failed22/29 6 empty 1 failed
.ppt 22 files16/22 6 empty16/22 4 empty 2 failednot supportednot supported
.odt 17 files15/17 2 failed15/17 1 empty 1 failed15/17 2 failednot supported
.msg 14 files14/1414/1413/14 1 failed14/14
.eml 9 files9/99/99/9not supported
.odp 4 filesnot supportednot supported2/4 2 emptynot supported
.ods 4 files3/4 1 emptynot supported4/4not supported
.csv 3 files3/33/33/33/3
.epub 3 files3/33/3not supported3/3
.json 2 files0/2 2 failed0/2 2 failednot supported2/2
.md 2 files2/22/22/22/2

OCR (image โ†’ text)

190 files from OCR test set (CORD receipts, DocLayNet pages, app screenshots); 190 of them give text to at least one library.
Library๐Ÿ”ด Fails where
another reads
๐ŸŸก Empty where
another reads
โฑ Hangs or
crashes
โœ… Words
found
Median
ms/file
Total
seconds
1 PaddleOCR 3.7.0
Note: With paddlepaddle 3.2.2, as its maintainers advise: with 3.3.1 (the default install) every image fails on CPU (PaddleOCR issue #18162). why
00095.1%30701,527.6
2 docTR 1.1.000095.0%2286864.8
3 RapidOCR 3.10.000092.4%372136.6
4 EasyOCR 1.7.200075.2%3736620.5
5 Tesseract 0.3.13 (tesseract 5.5.0)024067.5%13253.8

By kind of image: words found

ImagesPaddleOCRdocTRRapidOCREasyOCRTesseract
documents 50 images91.6%92.0%90.2%71.5%88.2%
receipts 80 images94.8%95.5%89.4%67.7%37.6%
screenshots 60 images98.5%96.9%98.4%88.2%90.0%

Speech to text (English)

130 files from Speech test set (LibriSpeech, FLEURS, AMI meetings, Earnings-22 calls); 130 of them give text to at least one library.
Library๐Ÿ”ด Fails where
another reads
๐ŸŸก Empty where
another reads
โฑ Hangs or
crashes
โœ… Word error
rate
Median
ms/file
Total
seconds
1 Parakeet 0.12.0 ยท model TDT 0.6B v2
Note: With huggingface-hub 1.31.0: with 1.32+ (new shared cache layout) and current onnxruntime, the model fails to load ("External data path escapes model directory"), as many other ONNX models do. why
00011.1%770124.2
2 faster-whisper 1.2.1 ยท model base.en int8
Note: With PyAV 18.1.0: faster-whisper 1.2.1 (the latest release) fails on every file with PyAV 19 (fixed on its main branch, not released yet). why
00016.8%46679.8
3 whisper.cpp 1.5.1 ยท model base.en00016.8%1226162.9
4 Whisper 20250625 ยท model base.en00017.6%1142164.9
5 Moonshine 20251121 ยท model base00019.8%1228167.9
6 Vosk 0.3.45 ยท model small en-us01037.1%918138.2

By kind of clip: word error rate

ClipsParakeetfaster-whisperwhisper.cppWhisperMoonshineVosk
ami-close-mic 20 clips12.4%22.7%23.4%22.7%18.3%44.3%
ami-far-field 15 clips29.3%47.6%46.6%49.0%50.5%79.3%
earnings-calls 25 clips19.1%24.5%23.9%26.6%37.5%60.4%
fleurs 20 clips9.3%12.4%12.9%12.9%14.8%32.5%
librispeech-clean 30 clips1.3%3.6%3.3%3.6%3.6%10.3%
librispeech-other 20 clips6.4%10.9%11.8%11.5%10.6%23.8%

Language detection

760 files from Language test set (Tatoeba sentences, 38 languages); 760 of them give text to at least one library.
Library๐Ÿ”ด Fails where
another reads
๐ŸŸก Empty where
another reads
โฑ Hangs or
crashes
โœ… CorrectMedian
ms/file
Total
seconds
1 py3langid 0.4.000097.0%<10.5
2 Lingua 2.2.000094.6%<10.5
3 fast-langdetect 1.1.0 ยท model fastText lid.176 (lite)00093.4%<11.5
4 langdetect 1.0.900093.0%11.3
5 langid 1.1.600089.1%12.5

By kind of text: share correct

Textspy3langidLinguafast-langdetectlangdetectlangid
paragraphs 190 texts99.0%97.4%95.8%99.5%99.5%
short-sentences 570 texts96.3%93.7%92.6%90.9%85.6%

โš”๏ธ Head to head

Any document โ†’ textmarkitdown vs DoclingAny document โ†’ textDocling vs UnstructuredAny document โ†’ textKreuzberg vs DoclingAny document โ†’ textmarkitdown vs UnstructuredAny document โ†’ textKreuzberg vs markitdownAny document โ†’ textKreuzberg vs UnstructuredPDFPyMuPDF vs pdfplumberPDFpypdf vs PyMuPDFPDFpdfplumber vs pypdfPDFpdfplumber vs pdfminer.sixPDFpypdf vs pdfminer.sixPDFPyMuPDF vs pypdfium2PDFmarkitdown vs PyMuPDFWord (.docx)python-docx vs docx2txtWord (.docx)mammoth vs python-docxWord (.docx)markitdown vs python-docxExcel (.xlsx)openpyxl vs python-calaminePowerPoint (.pptx)python-pptx vs markitdownOCR (image โ†’ text)EasyOCR vs TesseractOCR (image โ†’ text)PaddleOCR vs TesseractOCR (image โ†’ text)EasyOCR vs PaddleOCROCR (image โ†’ text)RapidOCR vs PaddleOCROCR (image โ†’ text)RapidOCR vs TesseractOCR (image โ†’ text)EasyOCR vs RapidOCROCR (image โ†’ text)docTR vs PaddleOCROCR (image โ†’ text)docTR vs TesseractSpeech to text (English)faster-whisper vs WhisperSpeech to text (English)faster-whisper vs whisper.cppSpeech to text (English)Vosk vs WhisperSpeech to text (English)faster-whisper vs VoskSpeech to text (English)Parakeet vs faster-whisperSpeech to text (English)Moonshine vs faster-whisperSpeech to text (English)whisper.cpp vs WhisperSpeech to text (English)Parakeet vs WhisperLanguage detectionlangdetect vs fast-langdetectLanguage detectionlangdetect vs LinguaLanguage detectionlangdetect vs langidLanguage detectionLingua vs fast-langdetectLanguage detectionpy3langid vs langidLanguage detectionLingua vs py3langid

How this is measured