Generate QR codes for any URL, text, or data with Python in minutes. You'll learn to create basic QR codes, customise the colours, add a logo in the centre, and batch-generate dozens of QR codes from a CSV file.
A Python script that takes any URL or text and generates a professional QR code image — custom brand colours, logo in the centre, saved as a PNG. Also includes a batch mode that reads a CSV and generates one QR per row.
QR codes are everywhere — event tickets, menus, business cards, product labels. Building your own generator means you can create them in bulk, brand them, and automate the whole process. Let's build it.
We need the qrcode library for generating QR codes, and Pillow for image manipulation (adding logos):
The [pil] part installs Pillow automatically alongside qrcode. Run this once and you're set.
Create qr_generator.py and generate a basic QR code in 5 lines:
Run it. Open myqr.png — you'll see a black and white QR code. Scan it with your phone and it opens the URL.
Use the QRCode class for full control over the output:
fill_color sets the QR dot colour. back_color sets the background. Use any hex colour or colour name. ERROR_CORRECT_H is required for adding a logo — it allows 30% of the QR to be covered.
Place a logo image in the middle of the QR code. The high error correction means it still scans perfectly:
RGBA mode). The mask=logo argument respects the transparency so the QR background shows through.Wrap everything into a clean, reusable function:
If you need dozens of QR codes — product pages, event tickets, business cards — read from a CSV:
Your qr_list.csv should look like:
Make your script accept input from the command line so you can use it like a tool:
Now run from the terminal:
One command, one QR code. You can use this in shell scripts or scheduled tasks.
You built a complete QR code generator — basic codes, branded colours, logo overlays, and batch CSV generation. This is a genuinely useful tool you can use right now for business cards, events, or product labels.
Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.