borb's README says commercial use requires a paid licence, its classifiers advertise Python 3.6, and it is one person's project
borb is a library for reading, creating and manipulating PDF files in python.
At a glance
- What is it?
- borb-pdf/borb is a PDF library that models documents as nested lists and dictionaries, at v3.0.9 with the last push on 2026-08-26. It is pure Python with no compiled dependency, and the licensing section is the first thing a commercial user needs to read: dual-licensed, with any paid or closed-source use requiring a purchased licence.
- Who is it for?
- borb is worth trying if you want to build PDFs from Python objects rather than by filling in a page template, because the document model is the design and the layout objects are the API. Two things to settle first.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 40 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Commercial use requires a paid licence, and the file says when
The licensing section is four paragraphs and it is the most consequential part of this README.
It states that the library is dual-licensed under the AGPL and a commercial licence, that the AGPL is an open-source licence, and that commercial use cases require a paid licence. Then it names three situations specifically.
Offering paid PDF services, with PDF generation in a cloud application given as the example. Using the library in closed-source projects. And distributing it in any closed-source product.
Those three cover most things a company might want to build. The first one in particular catches the case where the code is not sold but the output is, which is the arrangement most SaaS products use.
The commercial terms are not in the repository. The file links to the project site and says to contact the sales team, so the price, the term length and what counts as an internal use are all things you have to ask about rather than read.
What is in the tree is the free half: the AGPL text, a contributor agreement, a code of conduct, a security policy and a privacy policy. There is no commercial licence file, because the commercial side lives with the vendor.
The packaging claims three end-of-life Python versions and calls the project mature
The build script declares a maturity classifier and a list of supported interpreters, and the two do not sit comfortably together.
The status classifier is Development Status 6, Mature. The Python classifiers name 3.6, 3.7 and 3.8.
All three of those interpreter versions reached end of life years ago. The current release is 3.0.9, tagged in August 2026, and the last push to the default branch is dated 2026-08-26. So the metadata is advertising a floor three major versions behind the ecosystem while claiming maturity.
Classifiers are advisory and pip will not stop you installing on a newer interpreter, so this is not a hard failure. It is a signal about what gets maintained: the classifier list is the part of the metadata a maintainer usually updates when a release happens, and a stale list there suggests the packaging file has not been revisited.
The topic classifiers are also revealing, and oddly so for a PDF library: Artistic Software, File Formats, Text Processing, and two Multimedia entries. Text Processing and Artistic Software are how the author expects the library to be found.
There is also no pyproject file in the tree. The package is built by a single setup script with the author name and email inline, which is why the classifier list is the only machine-readable statement of what it supports.
It is one person's project and the examples live in a different repository
The overview section contains two sentences that together describe the project's shape better than any feature list.
It says the library was created and maintained as a solo project, and that it prioritises common PDF use cases for practical and straightforward usage.
Both are admissions, and both are the kind that make an evaluation easier rather than harder. A solo project means one maintainer decides what is supported, and the priority statement tells you that the goal is coverage of common cases rather than the whole PDF specification.
The examples reinforce the second sentence. Rather than shipping examples in the repository, the README points at a separate repository for them, and that repository is under a personal account rather than the organisation the library lives in. It is described as containing practical real-world applications, with five categories named: metadata management, text and image extraction, adding annotations such as notes and links, content manipulation covering text, images, tables and lists, and page layout management through the layout object.
So the practical shape is a library plus a detached gallery. Reading the source tells you the model, and reading the examples tells you the intended usage, and neither tells you what is deliberately not covered.
The API appends to objects and writes through a static call
The getting-started example is short enough to read in full, and its shape explains the model.
from pathlib import Path
from borb.pdf import Document, Page, PageLayout, SingleColumnLayout, Paragraph, PDF
# Create an empty Document
d: Document = Document()
# Create an empty Page
p: Page = Page()
d.append_page(p)
# Create a PageLayout
l: PageLayout = SingleColumnLayout(p)
# Add a Paragraph
l.append_layout_element(Paragraph('Hello World!'))
# Write the PDF
PDF.write(what=d, where_to="assets/output.pdf")Three things stand out. Pages are appended to the document. Layout objects are constructed against a page and elements are appended to the layout. And writing is not a method on the document: it is a call on the PDF class, taking what to write and where to write it.
That last one is a deliberate choice and it is the reason the layout types can be composed and handed around without the document needing to know about them. It also means a document cannot write itself, which is a small thing until you have a library object that is supposed to know how to persist.
The output path is worth noting too. It writes to a directory named assets, which the example assumes already exists. Nothing in the file creates it.
The documented way to get the latest version is to uninstall the package
The installation section has two parts, and the second is the one that stands out.
The first is a single command:
pip install borbThen a sentence introducing a way to ensure you have the latest version, followed by two commands:
pip uninstall borb
pip install --no-cache borbUninstalling first, then reinstalling with the cache disabled, is presented as the reliable route. That is not how a package index normally handles upgrades, and the reason is presumably a stale cached wheel rather than anything about the library.
It is worth reading as a small quality signal. A package that documents a reinstall-without-cache procedure is telling you that an ordinary upgrade has, at some point, not given you the new version. That can happen to anyone, but most libraries do not put it in the README.
There is nothing else in the installation section. No platform notes, no version constraints, and no mention of what the base install pulls in, because the dependency list lives in the build script's extra groups rather than in the file.
The full extra is computed from the others, and every extra has a comment
The build script's extras definition is the most careful piece of engineering in this repository, and it is worth reading because of how it is written rather than what it contains.
Five groups are declared. Development, with a formatter, a type checker and a docstring style checker, each with a trailing comment naming its purpose. Documentation, with a documentation generator and its theme. Generative AI, with one client library, commented as being used for generating images. Image, with charting, imaging, barcode, avatar and QR code libraries plus a download client. And text, with a font library and a download client.
Then the sixth group is not written out at all. It is computed as the sorted union of every other group except development and documentation, built from a set comprehension over the dictionary, which is what deduplicates the client library that appears in both the image group and the text group.
That is a genuinely good pattern. Adding a dependency to one group automatically adds it to the full install, and nothing can end up in the full install but not in its own group.
The naming is also consistent with the overview's scope statement. Nothing in the extras suggests an attempt to implement the whole PDF specification; they are the libraries needed to draw charts, place images, generate barcodes and embed fonts, which is a chart, image and text library with a PDF writer.
There is a privacy policy in a PDF library
The root listing contains seven documents, and one of them does not belong in this category at all.
There is a code of conduct, a contributing guide, a contributor licence agreement, the licence itself, a security policy, and a privacy policy.
A privacy policy in a library that runs entirely on your own machine and makes no network calls is unusual. It suggests either that the commercial side of the business processes data on the vendor's side, which the licensing section implies, or that the policy was added by habit.
The contributor licence agreement is a smaller surprise but points the same way. It is the paperwork you need when a project wants a patent grant from contributors on top of the copyright licence, which is a commercial-project practice rather than a hobby one.
Put the two together with the dual licensing and the picture is coherent: this is a project run as a business with a free tier for individuals and non-commercial work, and the legal surface in the repository is shaped accordingly.
The acknowledgements name three people and thank them for contributions and guidance, which is the only place in the file where outside input is credited.
Editorial conclusion
borb is worth trying if you want to build PDFs from Python objects rather than by filling in a page template, because the document model is the design and the layout objects are the API. Two things to settle first. Read the licensing section before you prototype, since the AGPL is only free for non-commercial use and the boundary the file draws is broad. And check the supported Python versions yourself, because the packaging metadata in the repository still lists three releases that have been end-of-life for years.
Frequently asked questions
Can I use borb in a commercial project?
Not under the AGPL alone. The README states the library is dual-licensed under AGPL and a commercial licence, and that commercial use cases require paying, specifically including offering paid PDF services, using it in closed-source projects, and distributing it in any closed-source product. The terms come from contacting the sales team.
How do I install borb?
With `pip install borb`. The README also documents `pip uninstall borb` followed by `pip install --no-cache borb` as the way to ensure you have the latest version.
What does the borb PDF document model look like?
It models a PDF as a JSON-like structure of nested lists, dictionaries and primitives. In code you build a document, append pages, construct a layout object against a page, append layout elements, and write the document with a static call that takes the document and an output path.
Which Python versions does borb support?
The packaging metadata in the repository lists 3.6, 3.7 and 3.8, all of which are end-of-life, while the current release is 3.0.9. Classifiers are advisory, so the metadata should not be treated as the current floor.
Where are the borb examples?
In a separate repository under the maintainer's personal account rather than the library's organisation, described as practical real-world applications covering metadata, text and image extraction, annotations, content manipulation and page layout. The library itself is built by a single setup script with no pyproject file.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/borb-pdf-borb)