DEV Community

IronSoftware
IronSoftware

Posted on

borb for Python: The Licence Decides Before You Ship

borb has two prices, and only one of them is money. The library ships under AGPL-3.0-or-later, where the fee is paid in source code that reaches the application importing it, with a commercial licence sold beside that for teams who would rather pay cash. The README names three situations that move a team onto the paid side, covering paid PDF services such as generation inside a cloud application, use in a closed-source project, and distribution inside one. Most pipelines are at least one of those, so the choice arrives before a project ships, unlike handing a template to a renderer under one commercial licence.

Full disclosure. We work on IronPDF at Iron Software. What follows weighs what borb's AGPL terms and single-maintainer model commit a project to, and how IronPDF renders markup a team already owns under one commercial licence.

The Paid Tier, the Add-Ons, and the Telemetry

The three cases above are not the whole of the paid side. Four capabilities sit outside the core library as separately sold add-ons, namely Markdown-to-PDF conversion, redaction, find-and-replace, and OCR, so a pipeline that needs any of them is buying twice. What follows here is what the project states about its own terms rather than a reading of what the AGPL requires for a given deployment, which is a question for your own counsel.

The library also ships licence verification and usage reporting of its own. A signed licence file registers at runtime to enable the commercial tier, and a separate usage-statistics module reports by default, sending licence state, page and document counts, platform, and library version, with a documented opt_out() call to stop it. That reporting only fires when requests is installed, which a bare install does not add. Projects running without a registered licence get a console reminder every 64 documents processed, and nothing else changes, since output is not watermarked, throttled, or blocked. IronPDF keeps the equivalent step to a licence key applied once at startup, with no runtime reporting attached to it.

Where Does the Object Model Stop?

Behind the licence sits more than a recent rewrite suggests. The project declares no required runtime dependencies, and image handling, barcodes, avatars, fonts, and outbound web requests all sit behind optional extras, which is a small surface for a security review to sign off. Behind that sit read, validate, and write pipelines built on close to seventy content-stream operators, a Source, Filter, and Sink pipeline that pulls text, images, colours, and keyword rankings by font, page, or spatial position, multi-column layouts, eighteen annotation types, form fields, and barcodes, QR codes, and charts as generated content. The companion examples repository, maintained by the same author, runs to hundreds of worked samples. For a pipeline whose documents are assembled entirely from structured data, that object model is the ceiling of what a code-first toolkit needs to reach, and IronPDF answers the markup half of the same pipeline from one commercial licence.

Composing a document means building a tree of Python objects.

from borb.pdf import Document, Page, PageLayout, SingleColumnLayout, PDF
from borb.pdf.layout_element.text.paragraph import Paragraph

document = Document()
page = Page()
document.append_page(page)
layout: PageLayout = SingleColumnLayout(page)
layout.append_layout_element(Paragraph("Hello World"))
PDF.write(what=document, where_to="output.pdf")
Enter fullscreen mode Exit fullscreen mode

That writes a one-page PDF with a single paragraph on it, and every further element arrives the same way, one constructor at a time. There is no markup-to-layout conversion anywhere in the codebase, and the only markup-shaped input borb accepts is a dedicated Markdown paragraph element, with full Markdown conversion sold as one of the paid add-ons. An invoice that already exists as an HTML template has to be rebuilt element by element through that API before borb can produce it.

Set the two scopes side by side and the split is clean, one library answering the half that starts in data and the other the half that starts in markup.

Capability borb IronPDF for Python
Existing HTML and CSS as input No HTML parser and no CSS support in the codebase Chromium engine through ChromePdfRenderer
Documents assembled from structured data Object composition, Paragraph into SingleColumnLayout Data merged into a template, then RenderHtmlAsPdf
Reading and modifying existing PDFs Read, validate, and write over close to 70 operators Load, edit, merge, and stamp on 1 PdfDocument
Text and image extraction Source, Filter, and Sink pipeline ExtractAllText plus image extraction, built in
Forms and annotations 18 annotation types and form fields Form fill, annotations, and encryption in 1 API
Install surface Core install, with images, barcodes, and fonts as extras One package, browser engine already inside
Licence AGPL-3.0-or-later, dual-licensed with paid commercial bands Commercial, one licence for every deployment
Python versions 3.6 and later per packaging metadata 3.7 and later, one wheel

Table 1. Document input and output paths only, borb against IronPDF for Python, with licence terms as each project states them.

The first row is the one that decides most migrations, because markup that already exists can go straight to a call that produces the document rather than through a constructor for every element on the page.

Who Ships the Next Release?

The README describes borb as created and maintained as a solo project, and the contributor list is one human account plus an automated dependency bot. Output has not slowed, with a release roughly every month to every quarter since 2021, including a full rewrite for the 3.x line and a release weeks before this comparison, and the packaging classifier lists development status as Mature. Depending on borb in production still means depending on the continuity of one person, which is a planning question for a document pipeline that has to outlive the people who set it up.

Advisories are not where the risk sits here. The GitHub Advisory Database's PyPI filter, Snyk, and the NVD carry no issue in borb's own code. A keyword search for the name surfaces two CVEs that belong to an unrelated WordPress plugin from Borbis Media rather than this library, which matters only when an automated scanner flags the string and someone has to explain it. What decides this choice sits in the licence band and the maintenance model rather than the advisory feed, and the documented API surface is where a like-for-like comparison actually happens.

Where the Job Outgrows an Object API

Most code-first pipelines end on a small request. A team starts in borb because the output is pure data, covering order confirmations, certificates, and internal reports, and then someone asks for the marketing team's branded cover page or the existing HTML email template. At that point an object-composition API and a browser engine stop being interchangeable.

from ironpdf import *

renderer = ChromePdfRenderer()
pdf = renderer.RenderHtmlAsPdf("""
<html>
<body style="font-family: sans-serif;">
    <h1>Invoice #4471</h1>
    <table style="width: 100%; border-collapse: collapse;">
        <tr><td>Consulting services</td><td style="text-align: right;">$2,400.00</td></tr>
    </table>
</body>
</html>
""")
pdf.SaveAs("invoice.pdf")
Enter fullscreen mode Exit fullscreen mode

That produces the invoice with its CSS applied exactly as a browser would paint it, without any of the markup being rebuilt through an object API first. IronPDF renders HTML and CSS from one package, so a template a designer already owns reaches PDF unchanged, and the same package covers the neighbouring jobs, including populating an existing PDF form rather than regenerating the document around it.

IronPDF renders the markup a team already owns under one commercial licence, with no copyleft obligation reaching into your source, no add-on to buy for a capability the pipeline already needed, and no single maintainer between the project and its next release. The narrow case that stays with borb is a document assembled entirely from structured data with no markup anywhere near it. IronPDF has a free trial if you want to run one of your existing templates through it before that licence conversation starts.

Where does your pipeline actually start, in code or in markup? If you are already running borb commercially, tell us in the comments how the licensing call went internally, because that conversation is the part nobody documents.

borb is the property of its author, and we have no affiliation with the project. The licence, pricing, and maintenance details above are taken from borb's own README, PyPI listing, and pricing page at the time of writing. If a detail has moved since, say so in the comments.

Top comments (0)