pure python · zero qr dependencies

Every QR code is a grid of squares.
Yours doesn't have to be.

BetterQR generates codes with real shapes, gradients, embedded logos, decorative frames, and animated GIFs — plus Micro QR and one-line WiFi, vCard, and geo codes. Style it however you like; it still has to scan, and it does.

$ pip install betterqr
View on GitHub

21×21 to 177×177 modules · ECC L / M / Q / H · PNG · JPG · SVG · PDF · EPS · GIF

Square-module QR code, decoded text: WIFI READY
Circle-module QR code, decoded text: https://betterqr.dev
Rounded-module gradient QR code, decoded text: SCAN ME
Diamond-module QR code, decoded text: PURE PYTHON
Star-module QR code, decoded text: HELLO WORLD
Gapped-module QR code, decoded text: MICRO QR
Vertical-bar gradient QR code, decoded text: 10 GIF FX
Horizontal-bar QR code, decoded text: 8 SHAPES
Circle-module QR code with contrast finder color, decoded text: FRAMES
Rounded-module radial gradient QR code, decoded text: V1-V40
Diamond-module radial gradient QR code, decoded text: ECC L-H
Rounded-module QR code with contrast finder color, decoded text: OPEN SOURCE

Every tile above is a real PNG made with BetterQR — scan one and see for yourself.

versions 1–40 + micro M1–M4 8 module shapes 4 gradient directions 10 animation effects 6 output formats 8 data-type helpers
what's built in

One library, every finish.

No plugins to install and no post-processing pipeline — styling, logos, frames, and animation all live in the same call chain as the QR generation itself.

Module shapes

Square modules Circle modules Rounded modules Diamond modules Star modules Gapped modules Vertical bar modules Horizontal bar modules

square, circle, rounded, diamond, star, gapped, and two bar styles — swap with one keyword argument.

Gradients

QR code with a radial violet-to-magenta gradient fill

Horizontal, vertical, diagonal, or radial — fade between any two colors across the whole code.

Logo embedding

QR code with a logo embedded in the center

Drop a PNG or JPG in the center. BetterQR raises error correction automatically so it still scans.

Frames & labels

Framed QR code with a caption label reading Visit our site

simple, rounded, double, shadow, or fancy — with a text label above or below, any color.

Animated GIFs

Looping animated QR code using the shimmer effect

shimmer, fade, scan, pulse, build, matrix, wave, blink, typewriter, rotate — the last frame is always fully scannable.

Data helpers

WiFi QR code Geolocation QR code SMS QR code Email QR code

WiFi, vCard, MeCard, geolocation, SMS, email, phone, and crypto — pass the helper object straight in.

Output formats

.png.jpg.svg .pdf.eps.gif

Raster for the web, vector for print — .save() picks the renderer from the file extension.

Colour control

#6D28D9#D97transparent

3- or 6-digit hex, transparent PNG backgrounds, and a separate colour just for the finder squares.

use it your way

Command line or Python — same feature set.

Reach for the CLI for a one-off code, or the fluent API when you're generating them in bulk.

# styled with a gradient
betterqr "Hello" my_qr.png --gradient "#FF6B6B" "#4ECDC4"

# logo + frame + label in one line
betterqr "https://mysite.com" qr.png --logo logo.png -e H --frame fancy --label "Scan Me!"

# WiFi, straight from the CLI
betterqr --wifi MySSID MyPassword wifi.png

# animated GIF
betterqr "Animated QR" animated.gif --effect matrix --fps 12
from betterqr import QR, WiFi

# chain style, logo, frame, and label
(QR("https://mysite.com", ecc="H")
    .style(shape="circle", fill="#6C3082")
    .logo("logo.png", ratio=0.25, shape="rounded")
    .frame("fancy")
    .label("Scan Me!")
    .save("framed.png"))

# data helpers pass in directly
QR(WiFi("MyNet", "MyPass", "WPA")).save("wifi.png")

# animation
QR("Hello", ecc="H", version=4).animate("matrix", fps=15).save("anim.gif")
for when space is tight

Micro QR, done properly.

All four Micro QR versions (M1–M4) with correct auto-version selection, so short payloads don't get padded out to a full-size symbol.

  • M1 — up to 5 numeric characters
  • M4 — up to 21 alphanumeric or 15 byte-mode characters
  • ECC L / M / Q (Micro QR has no ECC H)
Micro QR code, version M2
micro · 13×13
Standard QR code, version 1
standard · 21×21

Generate your first code in one line.

$ pip install betterqr
Read the docs