segno: A Pure Python QR Encoder That Also Writes SVG, EPS and PDF
Python QR Code and Micro QR Code encoder
At a glance
- What is it?
- segno is a BSD-3-Clause licensed pure Python QR Code and Micro QR Code generator with no dependencies, a command line interface and serializers for SVG, PNG, EPS, PDF, Netpbm and more. It suits Python developers who want standard conform codes without pulling in an image library.
- Who is it for?
- segno fits a Python project that needs a conformant QR code without adding a binary dependency, and it is the safer choice when the output has to be vector, since SVG, EPS and PDF writers come with no external library behind them. It is the wrong choice if you want colourful or animated artistic codes, since those need the separate qrcode-artistic plug-in, and it supports structured append, splitting a message across several QR codes, if that is what you need.
- Can I use it commercially?
- Yes. BSD-3-Clause 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 92 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 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A standard conform encoder with no dependencies
segno implements the ISO/IEC 18004:2015(E) QR Code bar code symbology specification and produces QR Codes and Micro QR Codes. The package is pure Python with no dependencies, and the dependency list in the package metadata reflects that: the single entry is `importlib-metadata>=3.6.0` guarded by a `python_version < '3.10'` marker, which exists only to read package metadata on older interpreters. Everything else is standard library, which is what makes it droppable into a service or a build script without a wheel to vendor. The project claims more than 1500 test cases with coverage at or above 98 percent to verify standard conform generation, and the package is classified as Development Status 5 - Production/Stable with a BSD licence.
The output format list is unusually long
The serialization formats are the reason many people pick this library. Segno provides Scalable Vector Graphics, Encapsulated PostScript, Portable Network Graphics, Portable Document Format, the Netpbm family of PAM, PBM and PPM, LaTeX in the form of PGF and TikZ, X PixMap and X Bitmap. None of these serializers require an external library, which means a vector PDF can be produced on a machine with nothing installed but Python. The vector formats matter for print and for large-format output, where a raster PNG scales badly, and the presence of PGF and TikZ means a code can be placed directly in a LaTeX document. The name comes from the Italian for sign or symbol, and the project is the work of Lars Heuer.
Micro QR codes appear without being asked for
The default behaviour catches people out. If the content is small enough, segno generates a Micro QR code, which is a smaller symbol with fewer modules and a more limited character set.
>>> import segno
>>> qrcode = segno.make('RAIN')
>>> qrcode.is_micro
True
>>> qrcode.designator
'M2-M'A Micro QR is denser but supports less, so a reader that only handles full QR codes will not read it. If that is not what you want, pass `micro=False` and you get a standard code instead.
>>> import segno
>>> qrcode = segno.make('RAIN', micro=False)
>>> qrcode.is_micro
False
>>> qrcode.designator
'1-H'There are also explicit factory functions. `segno.make_qr()` always produces a full QR code and `segno.make_micro()` always produces a Micro QR code, raising an error when the data is too large for one.
>>> micro_qrcode = segno.make_micro('Nick Cave and the Bad Seeds')
Traceback (most recent call last):
...
DataOverflowError: Data too large. No Micro QR Code can handle the provided dataSaving a code with scaling and colour options
The save call takes the output options, and the same object can be written in several formats. A minimal call writes a PNG.
import segno
qrcode = segno.make('Yellow Submarine')
qrcode.save('yellow-submarine.png')Scaling, colour and background are parameters on the same method, so a scaled transparent PNG and a dark-blue SVG differ only in the arguments.
>>> qrcode.save('up-jumped-the-devil-2.png', scale=10)
>>> qrcode.save('up-jumped-the-devil-3.png', light=None)
>>> qrcode.save('up-jumped-the-devil.pdf', scale=10)
>>> qrcode.save('up-jumped-the-devil.svg', scale=10, dark='darkblue')The `light=None` argument is the one to remember, since it produces transparent light modules rather than white ones. The designator attribute is worth knowing too, because it returns the version and the error correction level in one string, and it tells you what the encoder actually chose: the documented example picks a minimal version with an optimal error level without changing that version, returning `2-Q`.
The command line prints a code to your terminal
There is a console script, registered in the package metadata as the console script `segno`, pointing at `segno.cli:main`, and the simplest invocation prints a QR code to the terminal.
segno "Comfortably Numb"The output argument writes a file instead, and the same flags cover scale, colours and border.
segno -o=raincoat.svg "Famous Blue Raincoat"
segno --scale 10 --dark darkblue --border 0 --output=fire.svg "Who by Fire"
segno --scale 10 --light transparent --output=miracle.png "Waiting for the Miracle"The `--border 0` flag removes the quiet zone, the blank margin around the symbol that scanners rely on, so it is worth setting only when you already control the surrounding layout and want the code flush with other elements.
Installing it from PyPI, conda or a distro package
Installation is one command from PyPI.
pip install segnoIt is also on conda-forge.
conda install -c conda-forge segnoAnd Debian ships it under the name python3-segno.
apt-get install python3-segnoArch Linux has a package as well, called python-segno.
pacman -S python-segnoThe presence of distribution packages is a practical point for anyone running this in a locked-down environment, where pip may not be an option. The package metadata also pins the minimum interpreter at Python 3.5 and marks the project as Python 3 only.
Beyond plain codes: contact data, EPC, WIFI and structured append
Segno ships high level factories for the payloads people actually need to encode, including contact data in vCard and MeCard form, EPC QR Codes, and WIFI QR Codes carrying a network configuration. On top of that sits Structured Append mode, which splits a message across several QR codes and is the mechanism behind multi-part codes that a scanner reassembles. The main modes it supports are listed in the feature list along with Hanzi mode, which is the Chinese character mode of the specification. Two of the features are extensions rather than core: colourful QR codes, where the data is spread across module colours and which also work with Micro QR codes, and artistic QR codes, which require the separate qrcode-artistic plug-in and can even produce animated codes. Of these, only the artistic codes need the plug-in.
How it is built and packaged
The build uses flit_core as the build backend, and the version is dynamic, read from the source rather than duplicated in the metadata. The repository root shows a documentation directory, a `tests/` directory, a `sandbox/` directory and a `data/` directory, and the packaging configuration treats `data/` as external data for flit. Coverage is configured with branch coverage enabled. The source distribution explicitly includes the docs, the tests, the licence, the reStructuredText files, the noxfile and the manifest, and excludes the GitHub directory and the sandbox. A noxfile at the root is the usual sign that the test and lint sessions are managed with nox rather than a bespoke script. The examples directory covers Django, Flask, a logo case and plain text output, and the licence is BSD-3-Clause.
Editorial conclusion
segno fits a Python project that needs a conformant QR code without adding a binary dependency, and it is the safer choice when the output has to be vector, since SVG, EPS and PDF writers come with no external library behind them. It is the wrong choice if you want colourful or animated artistic codes, since those need the separate qrcode-artistic plug-in, and it supports structured append, splitting a message across several QR codes, if that is what you need. Before adopting it, check the micro behaviour, because segno.make returns a Micro QR code automatically when the content is short enough.
Frequently asked questions
Does segno need any third-party libraries?
No. It is a pure Python QR Code generator with no dependencies, and the only entry in the dependency list is importlib-metadata for interpreters older than Python 3.10. All serializers, including SVG, EPS and PDF, run without an external library.
How do I stop segno from generating a Micro QR code?
Pass micro=False to segno.make, which returns a standard QR code, or use segno.make_qr() to always get a full code. segno.make_micro() does the opposite and raises DataOverflowError when the data is too large for a Micro QR code.
Which output formats can segno write?
Scalable Vector Graphics, Encapsulated PostScript, PNG, PDF, the Netpbm formats PAM, PBM and PPM, LaTeX in PGF and TikZ form, X PixMap and X Bitmap. The console script can also print a code to the terminal.
How do I install segno?
With pip install segno from PyPI, with conda install -c conda-forge segno, or from a distribution package such as apt-get install python3-segno on Debian and pacman -S python-segno on Arch Linux.
Can segno create colourful or animated QR codes?
Colourful QR codes are supported by the core library, including for Micro QR codes. Artistic and animated codes require the separate qrcode-artistic plug-in, which is not part of this package.
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/heuer-segno)Was this useful?