PDF Library Benchmarks
This benchmark is about reading pure PDF files - not scanned documents and not documents that applied OCR.Benchmarking machine
Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz, CPython 3.14.7Every time is the shortest of three runs. To make the times less dependent on the machine, each one is divided by the time of a fixed pure-Python workload measured right before it, and multiplied by the time of that workload on the reference machine (Intel Core i7-6700HQ CPU @ 2.60GHz, CPython 3.14.7). The times are the seconds the reference machine would need. This works best for the pure-Python libraries (pypdf, pdfminer.six, pdfplumber), and roughly for the others.
Input Documents
| # | Name | File Size | Pages | | -: | :----------------------------------------------------------------------------------------------------------------------------------- | --------: | ----: | | 1 | 2201.00214 | 2.4MiB | 22 | | 2 | GeoTopo-book | 5.1MiB | 117 | | 3 | 2201.00151 | 1.5MiB | 12 | | 4 | 1707.09725 | 7.0MiB | 134 | | 5 | 2201.00021 | 2.6MiB | 10 | | 6 | 2201.00037 | 2.9MiB | 33 | | 7 | 2201.00069 | 14.7MiB | 15 | | 8 | 2201.00178 | 2.3MiB | 16 | | 9 | 2201.00201 | 1.3MiB | 9 | | 10 | 1602.06541 | 2.9MiB | 16 | | 11 | 2201.00200 | 284.8KiB | 7 | | 12 | 2201.00022 | 1.2MiB | 14 | | 13 | 2201.00029 | 797.6KiB | 12 | | 14 | 1601.03642 | 1004.9KiB | 8 |Libraries
| Name | Last PyPI Release | License | Version | Dependencies | Optional dependencies | | -----------: | :---------------- | ------------------------------: | -------: | :---------------------- | :-------------------------------------------------------------------------------------------------------------------- | | pypdfium2 | 2026-11-06 | Apache-2.0 or BSD-3-Clause | 5.15.0 | PDFium (Foxit/Google) | | | pdfminer.six | 2026-01-07 | MIT/X | 20260107 | | [image]: Pillow 13.0.0 | | pdfplumber | 2026-06-15 | MIT | 0.11.10 | pdfminer.six | | | pdfrw | 2017-09-18 | MIT | 0.4 | | | | pdftotext | - | GPL | 24.02.0 | Poppler (poppler-utils) | | | PyMuPDF | 2026-11-02 | GNU AFFERO GPL 3.0 / Commerical | 2.1 | MuPDF | | | pypdf | 2026-11-06 | BSD 3-Clause | 7.0.0 | | [full]: arabic-reshaper 3.1.0, brotli 1.2.1, cryptography 50.0.2, fonttools 4.68.0, pillow 13.0.0, python-bidi 0.6.12 | | Tika | 2026-08-01 | Apache v2 | 3.3.2 | Apache Tika | |Text Extraction Speed
| # | Library | Average | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | | :- | :-------------------------------------------------------- | :------ | :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | | 1 | pypdfium2 | 0.1s | 0.4s | 0.2s | 0.2s | 0.2s | 0.0s | 0.1s | 0.0s | 0.0s | 0.0s | 0.0s | 0.0s | 0.0s | 0.0s | 0.0s | | 2 | PyMuPDF | 0.1s | 0.4s | 0.2s | 0.2s | 0.2s | 0.0s | 0.1s | 0.1s | 0.0s | 0.0s | 0.1s | 0.0s | 0.0s | 0.0s | 0.0s | | 3 | Tika | 0.2s | 0.6s | 0.4s | 0.4s | 0.4s | 0.1s | 0.2s | 0.1s | 0.1s | 0.1s | 0.1s | 0.1s | 0.1s | 0.1s | 0.0s | | 4 | pdftotext | 0.3s | 0.7s | 0.9s | 0.3s | 0.7s | 0.1s | 0.2s | 0.3s | 0.1s | 0.1s | 0.1s | 0.1s | 0.1s | 0.0s | 0.0s | | 5 | pypdf | 1.8s | 12.6s | 3.6s | 2.8s | 2.0s | 0.4s | 1.0s | 0.4s | 0.4s | 0.4s | 0.6s | 0.4s | 0.5s | 0.3s | 0.2s | | 6 | pdfminer.six | 3.5s | 22.9s | 9.4s | 6.4s | 3.5s | 0.9s | 1.5s | 0.7s | 0.8s | 0.6s | 0.9s | 0.7s | 0.7s | 0.4s | 0.3s | | 7 | pdfplumber | 5.6s | 35.1s | 10.3s | 10.0s | 6.9s | 1.7s | 3.4s | 1.4s | 1.3s | 1.4s | 2.1s | 1.5s | 1.5s | 0.7s | 0.7s |
Image Extraction Speed
| # | Library | Average | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | | :- | :-------------------------------------------------------- | :------ | :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | | 1 | PyMuPDF | 0.5s | 0.3s | 0.4s | 0.0s | 1.6s | 0.4s | 0.0s | 2.7s | 0.3s | 0.3s | 0.1s | 0.0s | 0.2s | 0.2s | 0.0s | | 2 | pypdfium2 | 0.9s | 0.8s | 1.5s | 0.0s | 2.9s | 0.8s | 0.1s | 4.9s | 0.7s | 0.6s | 0.3s | 0.0s | 0.4s | 0.2s | 0.0s | | 3 | pypdf | 2.6s | 12.3s | 3.9s | 2.4s | 7.7s | 1.0s | 0.3s | 5.6s | 1.0s | 0.9s | 0.5s | 0.1s | 0.7s | 0.2s | 0.1s | | 4 | pdfminer.six | 4.5s | 26.7s | 9.6s | 7.2s | 10.7s | 1.0s | 1.6s | 1.2s | 0.9s | 0.6s | 1.0s | 0.7s | 0.8s | 0.5s | 0.3s |
Number of extracted images:
| Library | Total | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | | :-------------------------------------------------------- | :---- | :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | | PyMuPDF | 108 | 4 | 10 | 0 | 35 | 4 | 0 | 9 | 13 | 6 | 8 | 0 | 4 | 10 | 5 | | pypdfium2 | 135 | 21 | 10 | 8 | 35 | 4 | 0 | 9 | 15 | 6 | 8 | 0 | 4 | 10 | 5 | | pypdf | 184 | 38 | 10 | 42 | 35 | 4 | 0 | 9 | 13 | 6 | 8 | 0 | 4 | 10 | 5 | | pdfminer.six | 187 | 39 | 10 | 42 | 35 | 4 | 0 | 9 | 15 | 6 | 8 | 0 | 4 | 10 | 5 |
pypdf and PyMuPDF extract every image of a page once, pdfminer.six and pypdfium2 every time it is drawn. PyMuPDF does not extract inline images, and pypdfium2 fails on some of them.
Image Extraction Features
Which kinds of images the libraries extract, each tested with a small PDF.
| Feature | pypdfium2 | pdfminer.six | PyMuPDF | pypdf | | :---------------- | :-------: | :----------: | :-----: | :---: | | RGB, Flate | ✓ | ✓ | ✓ | ✓ | | JPEG | ✓ | ✓ | ✓ | ✓ | | JPEG 2000 | ✓ | ✓ | ✓ | ✓ | | Grayscale | ✓ | ✓ | ✓ | ✓ | | CMYK | ✓ | ✓ | ✓ | ✓ | | Indexed | ✓ | ◐ | ✓ | ✓ | | 16 bits | ◐ | ✗ | ✓ | ◐ | | 1 bit | ✓ | ✓ | ✓ | ✓ | | CCITT Group 4 | ✓ | ✓ | ✓ | ✓ | | LZW | ✓ | ✓ | ✓ | ✓ | | Filter chain | ✓ | ✓ | ✓ | ✓ | | Inline image | ✓ | ✓ | ✗ | ✓ | | In a form XObject | ✓ | ✓ | ✓ | ✓ | | Soft mask | ✓ | ✓ | ✓ | ✓ | | Stencil mask | ✓ | ✓ | ✓ | ✓ | | Drawn twice | 2 | 2 | 1 | 1 |
✓: the image is extracted. ◐: an image is extracted, but it is not the picture or cannot be opened. ✗: no image. ⚠: an error. For Drawn twice, the number of extracted images.
The features, and what went wrong
- RGB, Flate: 8 bits per component, FlateDecode.
- JPEG: DCTDecode.
- JPEG 2000: JPXDecode.
- Grayscale: DeviceGray.
- CMYK: DeviceCMYK.
- Indexed: A palette of 16 colors.
page-1-Im1.bmp: another picture (correlation -0.45)
- 16 bits: 16 bits per component.
page-1-image-1.jpg: another picture (correlation -0.04); pdfminer.six: no image; pypdf: Im1.png: another picture (correlation -0.04)
- 1 bit: Black and white, 1 bit per pixel.
- CCITT Group 4: CCITTFaxDecode, as in scanned documents.
- LZW: LZWDecode.
- Filter chain: ASCII85Decode and FlateDecode.
- Inline image: An image inside the content stream (BI ... ID ... EI).
no image
- In a form XObject: An image drawn by a form XObject.
- Soft mask: An image with an /SMask (transparency).
- Stencil mask: An /ImageMask, painted with the fill color.
- Drawn twice: The same image XObject drawn twice: the number of extracted images.
Watermarking Speed
| # | Library | Average | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | | :- | :--------------------------------------------------- | :------ | :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | | 1 | pdfrw | 0.1s | 0.0s | 0.3s | 0.0s | 0.2s | 0.1s | 0.0s | 0.1s | 0.1s | 0.0s | 0.1s | 0.0s | 0.1s | 0.0s | 0.0s | | 2 | PyMuPDF | 0.1s | 0.3s | 0.3s | 0.1s | 0.3s | 0.0s | 0.1s | 0.1s | 0.1s | 0.0s | 0.1s | 0.0s | 0.1s | 0.0s | 0.0s | | 3 | pypdf | 0.3s | 0.6s | 0.8s | 0.4s | 0.6s | 0.1s | 0.2s | 0.1s | 0.1s | 0.1s | 0.2s | 0.1s | 0.2s | 0.0s | 0.1s |
Watermarking File Size
| # | Library | Average | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | | :- | :--------------------------------------------------- | :------ | :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | | 1 | PyMuPDF | 3.5MB | 2.5MB | 5.7MB | 1.6MB | 7.3MB | 2.7MB | 3.1MB | 15.4MB | 2.4MB | 1.3MB | 3.0MB | 0.3MB | 1.2MB | 0.8MB | 1.0MB | | 2 | pypdf | 3.5MB | 2.5MB | 5.7MB | 1.6MB | 7.3MB | 2.7MB | 3.1MB | 15.4MB | 2.4MB | 1.3MB | 3.0MB | 0.3MB | 1.2MB | 0.8MB | 1.0MB | | 3 | pdfrw | 3.5MB | 2.5MB | 5.7MB | 1.6MB | 7.3MB | 2.7MB | 3.1MB | 15.4MB | 2.4MB | 1.3MB | 3.0MB | 0.3MB | 1.2MB | 0.8MB | 1.0MB |
Text Extraction Quality
| # | Library | Average | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | | :- | :-------------------------------------------------------- | :------ | :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | :-------------------------------------------- | | 1 | pypdfium2 | 95% | 94% | 97% | 94% | 99% | 95% | 96% | 99% | 97% | 99% | 99% | 98% | 78% | 90% | 99% | | 2 | PyMuPDF | 95% | 94% | 96% | 93% | 97% | 95% | 96% | 99% | 97% | 98% | 98% | 98% | 78% | 89% | 99% | | 3 | pypdf | 95% | 94% | 95% | 93% | 98% | 95% | 96% | 97% | 97% | 99% | 99% | 98% | 78% | 90% | 99% | | 4 | Tika | 94% | 94% | 99% | 92% | 97% | 95% | 96% | 93% | 95% | 98% | 94% | 98% | 73% | 90% | 96% | | 5 | pdftotext | 90% | 92% | 94% | 91% | 95% | 89% | 96% | 95% | 95% | 96% | 83% | 93% | 77% | 87% | 79% | | 6 | pdfminer.six | 89% | 91% | 79% | 87% | 92% | 83% | 94% | 96% | 92% | 92% | 93% | 94% | 71% | 89% | 86% | | 7 | pdfplumber | 74% | 89% | 84% | 68% | 97% | 58% | 94% | 61% | 88% | 57% | 59% | 67% | 58% | 89% | 67% |
Text Extraction Features
Which properties of a PDF the libraries handle, each tested with a small PDF. They explain some differences of the text extraction quality.
| Feature | pypdfium2 | pdfminer.six | pdfplumber | pdftotext | PyMuPDF | pypdf | Tika | | :---------------------- | :-------: | :----------: | :--------: | :-------: | :-----: | :---: | :--: | | Simple text | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Line break | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Space from a TJ offset | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Space from the position | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | WinAnsiEncoding | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Glyph names | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | CID font | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Right to left | ✓ | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ | | Type 3 font | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Form XObject | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Invisible text | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Rotated text | ✓ | ✗ | ✗ | ✓ | ✓ | ✓ | ✗ | | Superscript | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | Fake bold | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | | Two columns | ✗ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ |
✓: the expected text, ignoring whitespace except where the feature is about it. ✗: another text. ⚠: an error.
The features, and what went wrong
- Simple text: A line in a standard font, as a reference. Expected:
Hello World. - Line break: Two lines; the text must have a line break between them. Expected:
First line / Second line. - Space from a TJ offset: No space character; the words are apart by an offset in a TJ array, as pdfTeX writes most spaces. Expected:
Hello World. - Space from the position: No space character; every word is placed on its own. Expected:
Hello World. - WinAnsiEncoding: Characters of the codes 128 to 255 in WinAnsiEncoding. Expected:
€ “ä”. - Glyph names: No ToUnicode CMap; the /Differences of the encoding name the glyphs (alpha, beta, summation, minus), as in many fonts for math. Expected:
αβ∑−. - CID font: Two-byte codes of a Type0 font, mapped to Unicode by a ToUnicode CMap. Expected:
日本語. - Right to left: Hebrew letters, shown from left to right in the order they appear, so the last letter first. Expected:
שלום.
םולש; pdfplumber: םולש
- Type 3 font: A font whose glyphs are drawn by content streams, with glyph names. Expected:
Hi. - Form XObject: Text inside a form XObject. Expected:
Text in a form. - Invisible text: Text with rendering mode 3 (invisible), like the text layer of a scanned page. Expected:
Invisible text. - Rotated text: A line rotated by 90 degrees. Expected:
Rotated text.
t / x / e / t / d / e / t / a / t / o / R; pdfplumber: txet / detatoR; Tika: R / ot / at / ed / te / xt
- Superscript: A smaller digit raised with Ts. Expected:
E = mc2. - Fake bold: The same word drawn twice, 0.4 points apart, to look bold. Expected:
Bold.
BoldBold; pdfplumber: BBoolldd; PyMuPDF: Bold / Bold; pypdf: BoldBold; Tika: BoldBold
- Two columns: Two columns whose lines are written row by row; the left column must come first. Expected:
The left column starts / here and continues in / two more short lines / until it ends here. / The right column comes / after the left one and / has to be read after / the whole left column..
The left column starts The right column comes / here and continues in after the ; pdfplumber: The left column starts The right column comes / here and continues in after the ; PyMuPDF: The left column starts / The right column comes / here and continues in / after ; pypdf: The left column starts The right column comes / here and continues in after the ; Tika: The left column starts The right column comes / here and continues in after the