The Day I Realized PyMuPDF Is AGPL — Lessons from an OSS License Oversight


A library we picked “because it’s convenient” turned out to carry a source code disclosure obligation for our entire project.

If you do PDF processing in Python, PyMuPDF (fitz) is a go-to choice. It’s fast, and it handles text extraction, shape analysis, PDF generation, and merging — all in one package. Our team added it to requirements.txt without a second thought.

Then one day, during a dependency license audit, we noticed.

PyMuPDF’s license: AGPL-3.0.

What AGPL Means for Commercial Services

If you’re used to MIT and BSD, AGPL is easy to overlook — but it’s stricter than even GPL.

Standard GPL requires source code disclosure upon distribution. AGPL goes further: it triggers the same obligation when you provide a service over a network.

In other words, if your web application uses PyMuPDF for server-side PDF processing, you’re obligated to release the source code of your entire application under AGPL.

We had three options:

  1. Open-source everything under AGPL → not realistic for a commercial service
  2. Purchase a commercial license from Artifex → depends on cost
  3. Migrate to alternative libraries that don’t use AGPL

We chose option 3.

Breaking Away from the “One Library Does It All” Approach

PyMuPDF’s appeal was that it covered nearly every PDF operation in a single package. To migrate, we had to decompose that monolith into separate concerns.

Here’s what we ended up with:

Three libraries instead of one, but all MIT/BSD — no restrictions on commercial use.

The Hardest Parts of the Migration

The most technically challenging aspect was dealing with coordinate system differences.

PyMuPDF uses a top-left origin (like screen coordinates), while reportlab uses a bottom-left origin (the native PDF coordinate system). Every Y coordinate had to be transformed.

The other challenge was differences in text extraction data structures. PyMuPDF returns the PDF’s internal span structure directly, while pdfplumber returns character-level data. To accurately group text within table cells, we needed custom logic that combined character positions with gridline coordinates.

On the other hand, PDF merging (page assembly with clipping) — which we’d estimated as “the hardest part” — turned out to be surprisingly smooth. pypdf’s cropbox and Transformation API produced output identical to PyMuPDF.

Migration Approach: Incremental, Verification-First

We split the migration into six phases:

Phase 1: Start with the smallest, most isolated module (~300 lines) Phase 2-3: Core analysis and merge logic (adapter pattern to preserve existing logic) Phase 4: Discovered dead code → zero migration work needed Phase 5: PDF assembly migration Phase 6: Complete removal of PyMuPDF and Docker image cleanup

Before each phase, we ran quantitative comparisons between PyMuPDF and the replacement libraries. We verified that text, shapes, and merges all passed acceptance criteria across 8 real-world PDF forms (15 pages) before touching production code.

In Phase 4, we discovered that the text rendering feature we’d planned to migrate was actually dead code — never called anywhere. A strong reminder of why pre-migration inventory matters.

Lessons Learned

  1. Check the license first Before pip install, check the license on PyPI or GitHub. AGPL, GPL, and LGPL have vastly different implications for commercial use.

  2. “All-in-one convenience” carries risk Over-reliance on a single library amplifies the impact when that library becomes unusable. Design for separability, and migrations become much smoother.

  3. Quantitative comparison builds confidence “It should work” isn’t enough. “We verified identical output with numerical comparison” is what drives team-level decision-making.

  4. Find dead code before you migrate it There’s no need to migrate code that’s never called. Carefully tracing actual call paths before migration can dramatically reduce effort.

Summary

OSS license oversights are among the hardest forms of tech debt to spot. PyMuPDF is an excellent library, but if you can’t accept AGPL terms, alternatives exist.

The combination of pdfplumber + reportlab + pypdf covers PyMuPDF’s core functionality, and all are MIT/BSD licensed. The migration isn’t free, but with a phased, verification-driven approach, it’s entirely achievable.

Your project’s requirements.txt — when’s the last time you checked the licenses?

#OSS #Licensing #Python #PDF #AGPL #SoftwareDevelopment #TechDebt