Skip to main content
๐Ÿ›ก๏ธ Verified Technical Content: Written by Serhii Hrekov. | Last reviewed & updated in Git: August 14, 2026

Generating, Styling, and Decoding Barcodes & 2D Codes in Python: Complete Guide

ยท 6 min read
Serhii Hrekov
Senior Software Engineer & System Architect specializing in Python, Web Systems, Cloud Infrastructure & Automation

Generating and decoding barcodes is a foundational requirement across retail, inventory logistics, digital asset tracking, and ticketing systems. In Python, creating industry-standard 1D barcodes and 2D QR codes requires only a few lines of code with specialized libraries.

This guide provides a comprehensive manual on generating vector (SVG) and raster (PNG/JPEG) barcodes with python-barcode, styling dimensions, suppressing human-readable label text, and decoding codes in images or video streams with pyzbar and OpenCV.


Core Generation Toolkit: python-barcode and Pillowโ€‹

The python-barcode library supports all major 1D barcode symbologies, including EAN-13, Code 128, UPC-A, and ISBN-13. To output raster image formats (PNG, JPEG), install the optional pillow dependency.

Installationโ€‹

pip install "python-barcode[images]" Pillow pyzbar opencv-python

Barcode Symbology Selection Guideโ€‹

SymbologyCharacter Set & ConstraintsPrimary Industry Use Case
Code 128Full ASCII 128-character set (letters, digits, symbols).Logistics, warehouse bin tracking, shipping labels.
EAN-13Exactly 12 digits + 1 calculated checksum digit.International retail point-of-sale products.
UPC-A12 numeric digits.North American retail point-of-sale.
ISBN-1313 digits starting with 978 or 979.Book publishing and library cataloging.

Generating Vector and Raster Barcodesโ€‹

1. Generating Scalable SVG Barcodes (Default)โ€‹

SVGs are vector-based and infinitely scalable, making them ideal for web rendering:

import barcode

# Select Code 128 symbology
code128_cls = barcode.get_barcode_class("code128")
my_barcode = code128_cls("LOGISTICS-ASSET-98765")

# Save as SVG file (extension added automatically)
output_path = my_barcode.save("asset_tag")
print(f"Vector barcode written to: {output_path}")

2. Generating High-Resolution PNG Images with Custom Optionsโ€‹

For physical thermal printing, pass ImageWriter and configure module widths and quiet zones:

import barcode
from barcode.writer import ImageWriter

def generate_raster_barcode(data: str, filename: str):
code128_cls = barcode.get_barcode_class("code128")
my_barcode = code128_cls(data, writer=ImageWriter())

options = {
"module_width": 0.25, # Width of the thinnest bar (mm)
"module_height": 15.0, # Height of the bars (mm)
"font_size": 10, # Human-readable font size
"text_distance": 4.0, # Margin between bars and text label
"quiet_zone": 6.5, # White-space padding on edges
"background": "white",
"foreground": "black"
}

my_barcode.save(filename, options=options)

generate_raster_barcode("ASSET-ID-001", "asset_tag")

Removing Human-Readable Text Under Barcodesโ€‹

By default, python-barcode renders the encoded string directly beneath the bars. When creating compact labels, embedding barcodes into UI components, or generating machine-only scans, suppress the text using 'write_text': False:

import barcode
from barcode.writer import ImageWriter

def generate_textless_barcode(data: str, output_name: str):
ean_cls = barcode.get_barcode_class("ean13")
ean = ean_cls(data, writer=ImageWriter())

options = {
"write_text": False, # Suppresses human-readable label
"module_width": 0.3,
"module_height": 18.0,
"quiet_zone": 3.0
}

ean.save(output_name, options=options)

generate_textless_barcode("5901234123457", "barcode_no_text")

Generating Retail-Compliant EAN-13 Barcodesโ€‹

EAN-13 requires exactly 12 payload digits. The 13th modulo-10 checksum digit is calculated and appended automatically:

from barcode import EAN13
from barcode.writer import ImageWriter

def create_retail_ean13(twelve_digits: str, filename: str):
if len(twelve_digits) != 12 or not twelve_digits.isdigit():
raise ValueError("EAN-13 payload must be exactly 12 numeric digits.")

with open(f"{filename}.png", "wb") as f:
EAN13(twelve_digits, writer=ImageWriter()).write(f)

create_retail_ean13("123456789012", "retail_sku")

Decoding Barcodes and 2D Codes with pyzbar and OpenCVโ€‹

To detect and decode barcodes programmatically from static image files or camera video streams:

import cv2
from pyzbar.pyzbar import decode

def decode_barcode_image(image_path: str):
img = cv2.imread(image_path)
if img is None:
raise FileNotFoundError(f"Cannot open image: {image_path}")

detected_codes = decode(img)

for code in detected_codes:
payload = code.data.decode("utf-8")
symbology = code.type
bounding_box = code.rect
print(f"Decoded {symbology}: '{payload}' at {bounding_box}")

return detected_codes

if __name__ == "__main__":
decode_barcode_image("asset_tag.png")

Best Practices and Verificationโ€‹

  • Respect Quiet Zones: Maintain at least 10x the module width on both sides of the barcode. Truncating quiet zones prevents hardware scanners from establishing synchronization.
  • Test Physical DPI: Print barcodes at 300 DPI or higher to avoid aliasing artifacts that blur high-density symbologies (such as Code 128).
  • Hardware Validation: Always verify barcodes using physical handheld scanners and smartphone cameras prior to bulk printing.

Sources & Technical Referencesโ€‹

More on python