mrkeyoor.com_
Sat 07 Nov 06:52 UTC
PyPIUtilsupdated 07 Nov 2026

qrcode review

qrcode 8.2 is a Python encoder for standard QR Codes. Give it text or bytes and it can produce a PNG through Pillow or PyPNG, an SVG document, terminal characters, or the underlying module matrix for your own renderer. It does not read codes from photos and it does not generate Micro QR. The 8.2 release makes color-mask processing faster and fixes the spelling of the `embedded_image` arguments. The older `embeded_*` spellings still work for compatibility.

Verdict

qrcode 8.2 covers standard QR versions 1 through 40 and can emit PNG, SVG, terminal text, or a module matrix, but it cannot decode an image. Install an explicit renderer extra for ordinary QR generation, Segno for Micro QR, and pyzbar for scanning.

We installed it

Lab card: what happened when we installed qrcodeScreenshot of qrcode documentation
Install✓ · 0.2s1 package on disk · 1 MB
Import✓import qrcode in 0.09s · pure Python · requires Python >=3.9,<4.0
Known vulns0(pip-audit)

Answers from our run

Does qrcode install cleanly?

Yes. In a fresh container with an empty cache, pip install qrcode finished in 0.2s, leaving 1 package and 1 MB on disk. pip-audit reported no known vulnerabilities.

What does qrcode need to run?

Python >=3.9,<4.0, and nothing compiled: it is pure Python. In our run import qrcode succeeded in 0.09s.

qrcode or segno: which should you use?

segno: Choose it when the same Python API must create both standard QR and Micro QR symbols. qrcode 8.2 covers standard QR versions 1 through 40 and can emit PNG, SVG, terminal text, or a module matrix, but it cannot decode an image.

When should you not use qrcode?

You need to decode a camera frame or uploaded image. qrcode has an encoding API only. pyzbar is built for reading QR Codes and barcodes.

API stability4/5qrcode 8.2 retains the long-standing `QRCode`, `add_data()`, `make()`, `make_image()`, `get_matrix()`, and `qr` command interfaces. The release corrected `embedded_image` keyword spellings while continuing to accept the misspelled `embeded_*` forms. Major version 8 did drop Python 3.8 and older, and it now rejects embedded images unless error correction is set to H, so upgrades can expose an environment or runtime assumption.
Docs3/5The 8.2 README documents versions 1 through 40, all 4 correction levels, the 4-module border, SVG factories, terminal output, styled Pillow images, and the command-line flags with usable examples. Its installation section conflicts with the published metadata: the README says a standard install uses PyPNG, while PyPI lists PyPNG only under the `png` and `all` extras. That mismatch can turn the first PNG call into an avoidable deployment failure.
Maintenance3/5Version 8.2 reached PyPI on May 1, 2025, and no newer package release is listed. The unarchived GitHub repository was pushed on March 25, 2026 and currently reports 58 open issues and pull requests combined. Repository changes have not produced a package users can upgrade to, leaving the published build more than 1 year old. This is a small encoder rather than a network client, but unreleased fixes still leave users waiting.
Ecosystem4/5PyPI Stats counted 7,468,109 downloads in the latest week, and the GitHub repository has 4,947 stars. qrcode covers common Python output paths through Pillow, PyPNG, several SVG factories, terminal rendering, and direct matrix access. Its boundary is equally clear: decoding and barcode families outside standard QR live in separate packages, so projects that need a full scan-and-generate stack will assemble more than one dependency.

Use it if

  • A Python service needs to turn a URL, ticket token, Wi-Fi payload, or other short value into a standard QR Code.
  • You want to choose the QR version, error-correction level, module size, border width, colors, and image renderer in code.
  • The same payload must be available as PNG, SVG, terminal text, or a boolean matrix for a printer you already control.
  • A logo or shaped modules are required, and you can test every decorated result with the actual phones and scanners your users carry.
Skip it if

Setup reality

We did not install qrcode 8.2 for this guide, so we have no lab figures for install time, disk use, dependency count, import behavior, or vulnerability findings. PyPI serves a 45,986-byte universal wheel and declares Python >=3.9,<4.0.

No account, secret, or configuration file is involved. Image output is the setup trap. PyPI puts Pillow behind qrcode[pil] and PyPNG behind qrcode[png], yet the 8.2 README says a standard install uses PyPNG. Choose the renderer in your dependency file and in code. qrcode[pil] is the straightforward choice for colors, shaped modules, and embedded images. qrcode[png] supplies the pure-Python PNG path.

Automatic sizing can search standard QR versions 1 through 40. Leave version=None and call make(fit=True) when payload length varies. A fixed version with fit=False raises DataOverflowError instead of silently growing. Keep the default 4-module border unless your output specification says otherwise. An embedded image requires ERROR_CORRECT_H in 8.2, and the library raises ValueError when a lower correction level is used.

Generation runs synchronously inside the Python process. For an HTTP response, save into BytesIO rather than a temporary file. For a label printer, read get_matrix() and preserve its border. Styled output needs a scanner test after resizing or print conversion. The 8.2 README explicitly warns that custom shapes and color masks can fail with some readers, so a successful save() call is not a readability test.

Patterns

Save a QR Code as PNG save-png

import qrcode

image = qrcode.make("https://example.com/check-in/A7C2")
image.save("check-in.png")

This call needs an image renderer. Install `qrcode[pil]` when the application expects Pillow's PNG writer.

Build PNG bytes for an HTTP response return-png-bytes

from io import BytesIO

import qrcode

stream = BytesIO()
image = qrcode.make(payment_url)
image.save(stream, format="PNG")
png_body = stream.getvalue()

`BytesIO` avoids a temporary file, but it does not remove the renderer dependency. This example still expects `qrcode[pil]`.

Pick the smallest version that fits fit-smallest-version

import qrcode
from qrcode.constants import ERROR_CORRECT_Q

qr = qrcode.QRCode(
    version=None,
    error_correction=ERROR_CORRECT_Q,
    box_size=8,
    border=4,
)
qr.add_data(invite_url)
qr.make(fit=True)
image = qr.make_image(fill_color="#14213d", back_color="white")

`fit=True` searches QR versions 1 through 40. The 4-module border matches the minimum stated in the README.

Reject data that exceeds a fixed version catch-version-overflow

import qrcode
from qrcode.exceptions import DataOverflowError

qr = qrcode.QRCode(version=2)
qr.add_data(payload)
try:
    qr.make(fit=False)
except DataOverflowError as exc:
    raise ValueError("payload does not fit QR version 2") from exc

`fit=False` preserves version 2 and raises when the selected correction level leaves too little capacity.

Create a path-based SVG render-svg-path

import qrcode
from qrcode.image.svg import SvgPathImage

image = qrcode.make(
    manual_url,
    image_factory=SvgPathImage,
)
svg_markup = image.to_string(encoding="unicode")

`SvgPathImage` joins dark modules into one path, which avoids thin white seams when an SVG viewer scales the image.

Add a white background to SVG output render-svg-with-background

import qrcode
from qrcode.image.svg import SvgPathFillImage

image = qrcode.make(
    document_url,
    image_factory=SvgPathFillImage,
)
image.save("document-code.svg")

`SvgPathFillImage` inserts a white rectangle behind the modules. `SvgPathImage` leaves that background unspecified.

Select the pure-Python PNG renderer use-pypng-renderer

import qrcode
from qrcode.image.pure import PyPNGImage

image = qrcode.make(
    shipping_label,
    image_factory=PyPNGImage,
)
image.save("shipping-code.png")

`PyPNGImage` requires the `pypng` distribution. PyPI exposes it through the `qrcode[png]` extra.

Capture a terminal-safe text rendering capture-terminal-output

from io import StringIO

import qrcode

qr = qrcode.QRCode()
qr.add_data("otpauth://totp/Example:dev")
output = StringIO()
qr.print_ascii(out=output, invert=True)
terminal_text = output.getvalue()

`print_ascii()` does not need Pillow or PyPNG. The `invert` flag swaps the text foreground and background.

Send the module matrix to a printer read-module-matrix

import qrcode

qr = qrcode.QRCode(border=4)
qr.add_data(label_payload)
qr.make(fit=True)

for row_index, row in enumerate(qr.get_matrix()):
    label_printer.draw_modules(row_index, row)

`get_matrix()` includes the configured border. Keep all 4 blank edge modules when the printer lays out the final symbol.

Draw rounded Pillow modules draw-rounded-modules

import qrcode
from qrcode.image.styledpil import StyledPilImage
from qrcode.image.styles.moduledrawers.pil import RoundedModuleDrawer

qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_Q)
qr.add_data(campaign_url)
qr.make(fit=True)
image = qr.make_image(
    image_factory=StyledPilImage,
    module_drawer=RoundedModuleDrawer(),
)

Rounded modules require Pillow and can reduce scanner tolerance. Test the exported size on the readers that matter.

Place a logo in the center embed-center-image

import qrcode
from qrcode.constants import ERROR_CORRECT_H
from qrcode.image.styledpil import StyledPilImage

qr = qrcode.QRCode(error_correction=ERROR_CORRECT_H)
qr.add_data(landing_url)
qr.make(fit=True)
image = qr.make_image(
    image_factory=StyledPilImage,
    embedded_image_path="logo.png",
)

Version 8.2 requires H correction for embedded images and accepts the correctly spelled `embedded_image_path` keyword.

Choose command-line output explicitly generate-from-cli

qr --output=asset.png "inventory:4821"
qr --factory=svg-path "https://example.com/help" > help.svg
qr --ascii "terminal value" > code.txt

The `qr` command can write PNG, SVG, or ASCII. Use `--output` for binary PNG on PowerShell instead of redirecting standard output.

Alternatives

PackageRegistryPick it when
segnoPyPIChoose it when the same Python API must create both standard QR and Micro QR symbols.
qrcodegenPyPIChoose it for a compact QR encoder when you do not need qrcode's Pillow styling helpers.
treepoemPyPIChoose it when QR output belongs beside Aztec, PDF417, Code 128, and many other barcode formats.
pyzbarPyPIChoose it when the job is to read QR Codes and one-dimensional barcodes from images.

More utils guides

lru-cache · type-fest · ajv · zod · p-limit · find-up · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.