Open-source project
WhyNotHugo/python-barcode avatar
WhyNotHugo/python-barcode

python-barcode draws SVG barcodes with no dependency at all

㊙️ Create standard barcodes with Python. No external dependencies. 100% Organic Python.

658 stars138 forksPythonMIT

At a glance

What is it?
python-barcode is a small MIT licensed library that renders standard barcodes, writing SVG with pure Python and raster images through Pillow when you need them. Its appeal is that it has no mandatory dependency and ships a console script, and its limits are that the documented surface in the README is thin and the packaging still depends on a font file bundled in the package.
Who is it for?
Adopt python-barcode if you need a standard barcode in a build step, a PDF or an SVG and you would rather not add a binary barcode dependency to your environment, since the SVG path has no mandatory dependency and the code is small enough to read. Do not adopt it if you need a barcode symbology it does not implement, because the README does not enumerate the supported code types, and do not expect a modern release cadence from the tag list alone.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 14 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 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A barcode library whose selling point is the absence of dependencies

python-barcode is described as providing a simple way to create barcodes in Python, and the project description makes the dependency claim explicit: no external dependencies, 100% organic Python.

The README states the rule precisely. There are no external dependencies when generating SVG files, and Pillow is required for generating images, for example PNGs. Support is for Python 3.11 to 3.15.

That split is the design decision, and everything else follows from it. SVG is a text format, so a barcode rendered as SVG is a set of rectangles or paths in a document, and generating that requires nothing but the standard library. A raster image, on the other hand, needs a rasteriser and an encoder, which is what Pillow provides. So the library can offer a genuinely zero-dependency path for the case where a vector barcode is acceptable, and an optional dependency for the case where it is not.

The project is MIT licensed, with the licence file named LICENCE, and the documentation is published at python-barcode.rtfd.io and can be built locally with make -C docs html.

The project is classified as Development Status 5 - Production/Stable in the package metadata, and the repository is not archived with the last push on 2026-10-09. The release tags in the repository list are v0.14.0, v0.13.1 and v0.13.0, with the newest dated 2022-05-17, which is a gap worth understanding rather than worrying about, because the version is not written by hand.

The top level of the repository is small and legible: a barcode package directory, a docs directory, a tests directory, a tox.ini, a CHANGELOG.rst, an example-ean13.png, and a publish-release.yaml workflow. An example image of an EAN-13 barcode is checked in at the root, which is a small sign of what the output is supposed to look like.

How the version is derived, and why the tag list misleads

The most interesting thing in the packaging metadata is a single line.

toml
[tool.setuptools_scm]
write_to = "barcode/version.py"
version_scheme = "post-release"

setuptools_scm derives the version from the version control metadata rather than from a literal in the source, and it writes the result into barcode/version.py at build time. The project declares the version as dynamic in the metadata, so there is no version string to read in the pyproject.toml.

This is why the release tag list in the repository facts stops at v0.14.0 from 2022 while the last push is from October 2026. Tags are created by the release workflow, and the publish-release.yaml file in the repository root is what drives it, so a repository can receive work for a long time between published versions. The version_scheme setting of post-release also changes how the tag is interpreted, since a post-release scheme derives the version from the tag rather than treating a plain tag as a release.

For a consumer, the practical consequence is that you should pin the version you installed and record it, rather than assuming the newest tag reflects the newest code. And for a user running from a source checkout, the version file is generated rather than committed, which is the usual setuptools_scm arrangement.

The rest of the build configuration is conventional and healthy. The build backend is setuptools with a requirement of setuptools 61 or newer, wheel, and setuptools_scm 6.2 or newer, and the project is a src-less layout with the barcode directory at the root of the repository, discovered by the setuptools package find configuration. The ruff configuration is extensive, extending the default rule set with ANN for type annotations, the pycodestyle error and warning rules, the isort rules, the naming rules, the pyupgrade rules, the flake8 2020 rules, the bugbear rules, the comprehensions rules, and more, which tells you the maintainer treats typing and style as part of the contract rather than as an afterthought.

The optional image extra and the console script

Two configuration details decide how you install and how you call the library.

The first is the extra:

toml
[project.optional-dependencies]
images = ["pillow"]

The extra is named images and it contains a single dependency, pillow. The README's phrasing, that Pillow is required for generating images, is the user-facing version of this. The important detail is that the extra is opt-in, so an environment that only ever emits SVG does not need Pillow installed at all, and an environment that does need PNG output asks for it explicitly.

The second is the console script:

toml
[project.scripts]
python-barcode = "barcode.pybarcode:main"

The package installs a command named python-barcode that dispatches to the main function in the pybarcode module inside the barcode package. The name of that module is a leftover from the project's earlier layout, when the package was a single module, and it is the kind of detail that matters if you write a wrapper script around the CLI.

The package data declaration shows where the rendering resources live:

toml
[tool.setuptools.package-data]
barcode = ["barcode/fonts/*.ttf"]

The font files are shipped inside the package, under barcode/fonts. That is worth noting because it qualifies the no-dependency claim in a useful way. The library does not depend on a system font or on a font package you have to install, and the human-readable text under a barcode is rendered with a bundled TrueType font rather than whatever the host happens to have installed. It also means the package carries binary assets, which is worth remembering if you are building a minimal container image or trimming a wheel.

Getting the library and the documentation in place

The package is on PyPI under the name python-barcode, and the documentation site is the reference for the API. The README says the full documentation is published at http://python-barcode.rtfd.io/, and you can build the documentation locally with make -C docs html, which is the command to run if you want to work against the version in your checkout rather than the published one.

For a local install, the pyproject.toml tells you what the build expects. The build backend is setuptools with setuptools 61 or newer, wheel, and setuptools_scm 6.2 or newer, and because the version is derived from version control metadata, a source checkout needs its git history present for the version to be determined at all. The package lives in a barcode directory at the root of the repository, with the fonts under barcode/fonts inside it, and the console script is named python-barcode.

The dependency decision is the one to make explicitly at install time. If your output is SVG, you need nothing beyond the library itself. If you want a PNG or another raster image, you need Pillow, and the extra named images is the way to ask for it rather than installing it by hand into the environment.

The test suite is set up with pytest and tox, with a tox.ini at the repository root and a pre-commit configuration, so a contributor's loop is the usual one: run the tests, run the linter, and check the CHANGELOG.

Where python-barcode is the wrong tool

Three limits, and the first is the one the README is least forthcoming about.

The first is that the supported symbologies are not documented in the README. The README gives one example image, an EAN-13, and the words standard barcodes, but it does not enumerate which code types the library implements. The project is a well known one in the Python ecosystem and the package contains the implementations, so this is a documentation gap rather than a functional one, but it is the gap that matters when you are choosing a library. Whether your identifier is EAN-13, UPC-A, Code 128, Code 39, ISBN-13 or something else changes whether the library is usable at all, and the README does not answer that.

The second is that the output is a rendering, not a specification of a barcode. The library produces an image, either SVG or a raster, and it is the image that a scanner reads. There is no discussion in the README of the data encodings themselves, of check digits, of the quiet zones that a scanner needs to find the symbol, or of the printing resolution requirements that decide whether a barcode scans at all. A barcode that renders but does not scan is a silent failure, and the README does not give you the constraints to check against.

The third is the versioning question again, from a different angle. The release tags stop in 2022 while the code has been pushed as recently as October 2026, so a team pinning a version has to decide whether to trust the tag or the branch, and the dynamic version scheme makes the answer depend on how the package was installed. For a library whose job is to produce an artefact that has to be correct, that is an unusual amount of ambiguity to live with.

The alternative approach, and it is worth weighing, is to reach for a barcode library that documents its symbologies, or for a service that issues barcodes as part of a product you already pay for. The difference in approach is that python-barcode is a rendering tool with no dependencies and no service, and it will happily draw anything its code supports, whereas a hosted issuing service gives you a guaranteed-scannable symbol and handles the encoding rules for you, at the cost of a network dependency and a service to depend on.

Editorial conclusion

Adopt python-barcode if you need a standard barcode in a build step, a PDF or an SVG and you would rather not add a binary barcode dependency to your environment, since the SVG path has no mandatory dependency and the code is small enough to read. Do not adopt it if you need a barcode symbology it does not implement, because the README does not enumerate the supported code types, and do not expect a modern release cadence from the tag list alone. Verify first which symbologies the installed version actually supports by reading the barcode package, that you install Pillow explicitly if you want PNG output rather than relying on the empty-by-default behaviour, that the console script named python-barcode is the entry point you want, and that the version you pin matches what you tested, since the version is derived by setuptools_scm rather than written by hand.

Frequently asked questions

Does python-barcode need any dependencies?

There are no external dependencies when generating SVG files, and Pillow is required for generating images such as PNGs. The optional dependency group is named images and contains pillow, and the README states support for Python 3.11 to 3.15.

How is the python-barcode version determined?

The version is dynamic and derived by setuptools_scm, which writes it to barcode/version.py at build time, using a post-release version scheme. The build backend is setuptools with setuptools_scm 6.2 or newer among the requirements, and the project declares dynamic = ["version"] in its metadata.

Does python-barcode install a command line tool?

Yes. The project defines a console script named python-barcode that points at barcode.pybarcode:main, so the package can be driven from a shell as well as imported.

What licence is python-barcode released under?

It is MIT licensed, recorded in the package metadata as license = { text = "MIT" } and described in the README as licensed under the MIT licence, with details in the LICENCE file at the repository root.

Which barcode types does python-barcode support?

The README does not enumerate them. It describes the project as creating standard barcodes, ships an example EAN-13 image, and the supported types are defined by the code in the barcode package, so you need to check the installed version for the symbologies you need.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. WhyNotHugo/python-barcode on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/whynothugo-python-barcode.svg)](https://hysenlabs.com/projects/whynothugo-python-barcode)

Was this useful?