Many Hong Kong SMEs use QR codes every day: a restaurant needs one per table for the menu and ordering, an online shop needs one per product, events need a check-in code, and flyers and business cards need one to link to a website. The problem is that most owners and staff generate them one at a time on a free website — slow, with messy filenames, and no way to add their own logo or brand colours. Asking for a few hundred at once is enough to wear anyone out.
With Python and the free qrcode library, a dozen lines of code generate them in bulk, with logos, custom colours and filenames taken straight from an Excel list. Even if you have never written code, you can follow along.
What is a QR code, and why generate them in bulk?
At heart, a QR code turns a web address or a piece of text into a grid of black-and-white squares that a phone camera can read in a single scan. A single code is easy — any free website will do it. But when you need "one code for each of dozens of branches" or "one code for each of hundreds of products", doing it by hand simply does not scale: it is slow, easy to mix up and impossible to style.
Generating them with a program is different: read a whole Excel list at once, name and lay them out automatically, and keep the style consistent. Changing a colour or adding a logo is a one-line setting, and adding a new product or branch later is just a new row and one more run.
Step 1: Install the tools
Open Command Prompt and install two packages: qrcode to generate the codes and Pillow to draw and paste the logo.
(If you are not using an Excel list, you can skip pandas and openpyxl.)
Step 2: The simplest version — one QR code
Create a new file called qr.py (Notepad is fine) and paste this in:
Run python qr.py and a qrcode.png appears in the same folder — scan it with your phone and the site opens. qrcode.make() picks sensible settings for you, making it the easiest way to start.
Step 3: Bulk generation — hundreds from one Excel list
Say you have an Excel file called links.xlsx with two columns: name (for example a product code or branch) and url (the link to encode). Create an out folder beside it and run:
Line by line
- pd.read_excel("links.xlsx") — loads the list, one row per QR code.
- for _, row in df.iterrows() — works through the rows; row["url"] is the link and row["name"] becomes the filename.
- error_correction=ERROR_CORRECT_H — the highest level (about 30%), so the code still scans even if part of it is smudged or a logo sits in the centre.
- box_size=10 — each square is 10 pixels; larger numbers give a bigger, clearer image.
- border=4 — the width of the quiet zone in squares. Too little white space and many scanners fail, so do not shrink it.
- qr.add_data(...) with qr.make(fit=True) — encodes the link and picks the smallest version that fits.
- fill_color / back_color — set the colours, for example dark grey on white; make sure the contrast is strong.
- img.save("out/%s.png" % row["name"]) — names each file after the list entry, so everything is easy to find.
Step 4: Add your logo in the middle
Want a logo in the centre for a nicer, more recognisable code? Remember that Step 3 must use the highest error correction (H) to leave room for it. Add these lines at the end:
Keep the logo under 25% of the code's width — any bigger and it covers too many squares and the code stops scanning. After generating, always test-scan with a real phone before you print.
Real uses for Hong Kong SMEs
- Restaurants and cafes — one code per table so guests can view the menu and order.
- Retail and online shops — one code per item, linking to product info, warranty registration or an offer.
- Events and exhibitions — a check-in code that guests scan to register instantly, with no signing queue.
- Marketing — flyers, posters and cards that open a website or a WhatsApp chat in one scan.
- Internal operations — codes on equipment or shelves that reveal maintenance logs or stock on the spot.
A real example: for an online shop with 200 products, generating each code by hand — renaming and downloading files — takes roughly three to four hours. The script above produces all 200 in a few seconds, with tidy filenames to match.
Five practical tips
- Use error correction H (30%) — it leaves the most room, so a logo or a slight printing variation still scans.
- Keep the border at 4 or more — without enough quiet zone, many scanners will not read the code.
- Keep the contrast strong — a dark code on a light background is safest; light codes on dark backgrounds fail on some older phones.
- Keep the logo under 25% — cover too many squares and error correction can no longer cope.
- Always test-scan before printing — scan with a real phone's front and rear cameras to confirm it works before sending to print.
Summary
Python Tutorial: With a dozen lines of code you fully automate the "generate each QR code by hand on a website" chore — from one Excel list, a few seconds produces hundreds of codes, all consistently styled, with logos and custom colours. Whether it is menus, product labels, event check-ins or flyers, you save a huge amount of time and end up with a tidier, more professional result. Next, you can add Pillow layout code to arrange dozens of codes onto a single A4 sticker PDF and hand it straight to the printer.