Developer

How to Create QR Codes That Actually Scan

QR codes fail for boring, fixable reasons. Learn error correction levels, quiet zones, contrast, sizing, and static vs dynamic codes before you hit print.

Try it now: QR Code Generator Create custom QR codes — free, no signup, runs in your browser.

Five thousand flyers come back from the printer. The design is beautiful. The QR code in the corner — printed small, on a dark navy background, with the logo dropped in the middle — takes four or five seconds to scan, if it scans at all. There is no fixing it now.

QR codes almost never fail for mysterious reasons. They fail for a handful of specific, avoidable ones, and every single one is decided before you export the file.

What a QR code actually contains

A QR code is not a link to anything. It is a two-dimensional barcode holding text — that is the whole of it. Your phone’s camera reads the text, notices it looks like a URL, and offers to open it.

So a QR code can hold anything expressible as a string:

  • A URL — by far the most common use.
  • Plain text — a serial number, a room name, instructions.
  • Wi-Fi credentials — a formatted string like WIFI:T:WPA;S:NetworkName;P:password123;; that phones recognise and offer to join.
  • Contact details — vCard or MECARD text, which most cameras offer to save as a contact.
  • tel: and mailto: links — to start a call or a pre-addressed email.

The important consequence: the more text you encode, the denser the code becomes. QR codes come in sizes called versions, from 21×21 modules (the little squares) up to 177×177. More data forces a higher version, which means more modules packed into the same physical space, which means each module is smaller and harder for a camera to resolve.

Everything below follows from that one trade-off.

Error correction levels: the real trade-off

QR codes use Reed–Solomon error correction, so a partly damaged or obscured code can still be decoded. You choose how much redundancy to bake in:

LevelApprox. data recoverableTypical use
L (Low)~7%Clean digital display, long URLs
M (Medium)~15%The sensible default for print
Q (Quartile)~25%Rough surfaces, industrial labels
H (High)~30%Codes with a logo overlaid

The catch: error correction is not free. The redundant data occupies space in the code, so switching from L to H on the same URL pushes it to a higher version with more, smaller modules. A level-H code is more resistant to damage but harder to scan at a distance, because each module is physically smaller at the same print size.

So the rule is not “always use H”. It is:

  • Putting a logo in the middle? Use H, and keep the logo under roughly 30% of the code’s area. Anything larger destroys data the correction can no longer rebuild.
  • Printing on something that will be handled, folded, or rained on? Q.
  • Everything else? M.

Shorter URLs make better codes

This is the highest-leverage thing you can do, and it costs nothing. Compare what you are asking the code to hold:

https://example.com/products/summer-collection-2026?utm_source=flyer&utm_medium=print&utm_campaign=spring_launch

versus:

https://example.com/summer

The first forces a much denser code. The second produces large, forgiving modules that scan instantly from across a room. If you need campaign tracking, use a short path on your own domain and handle tracking server-side.

Clean, lowercase, hyphenated paths encode compactly and are easy to type as a fallback — the Slug Generator turns a page title into exactly that. If a parameter you keep contains spaces or special characters, percent-encode it with the URL Encoder / Decoder; an unencoded space or ampersand breaks the destination even when the code scans perfectly.

Contrast, inversion, and colour

Scanners look for dark modules on a light background. That expectation is baked into how decoders locate the finder patterns in the corners.

Which leads to the most common design mistake: inverted codes, light modules on a dark background. Some modern camera apps handle them; plenty do not, and cheaper scanners are worse. For a printed poster read by strangers with unknown phones, an inverted code is a gamble with no upside.

  • Keep modules substantially darker than the background — high contrast beats brand consistency here.
  • Coloured modules are fine if they stay dark. Deep navy or forest green on white works; pastels, yellows, and mid-greys do not.
  • Avoid gradients, and never place a code over a photo or busy texture.
  • On glossy stock, expect glare; matte finishes scan more reliably.

The quiet zone

A QR code needs an empty margin around it — the quiet zone — so the decoder can tell where the code ends. The specification calls for a border of four modules’ width on all four sides.

Designers delete this constantly, cropping tight to the pattern to save space or butting the code against a coloured block. The code then either fails outright or gets fussy about angle and distance. Leave the margin, and keep it the same colour as the code’s light background.

Size and scan distance

A widely used rule of thumb: the code should be about one-tenth of the distance you expect people to scan from.

  • Scanned from ~30 cm (a business card or menu): at least ~3 cm across.
  • Scanned from ~3 m (a shop window or wall poster): at least ~30 cm across.

Roughly 2 cm square is a sensible practical floor for close-range print. Below that, paper texture, ink spread, and camera focus all start working against you. And a denser code — more data, or higher error correction — needs to be printed larger to keep its modules the same physical size.

Always export at high resolution, or better, export SVG: a vector code scales to any size with perfectly crisp edges, which matters enormously in print. The QR Code Generator offers both PNG and SVG output.

Static vs dynamic: the honest trade-off

Static QR codes encode the destination directly — the URL is physically in the pattern. It cannot be changed, tracked, or expired. It will work in ten years exactly as it works today.

Dynamic QR codes encode a short link belonging to a third-party service, which redirects to your real destination. You get editable destinations and scan analytics.

The part the marketing pages underplay: a dynamic code is only alive as long as that redirect service is. If the company shuts down, changes its pricing, or your subscription lapses, every code you printed becomes a dead link — and you cannot patch paper. For anything permanent (packaging, signage, equipment labels), that is a risk to accept knowingly rather than by accident.

There is a middle path with none of the dependency: generate a static code pointing at a short URL on your own domain, and configure the redirect on your own server. You can change the destination whenever you like, you get analytics from your own logs, and nobody else’s business model can break your print run.

Test before you print

Generating the code takes ten seconds. Testing it takes five minutes and saves reprints.

  • Scan with at least three devices, mixing iPhone and Android, using the built-in camera app rather than a scanner app — that is what real people use.
  • Test at the actual final size. Print a proof; do not judge it at 400% zoom on a monitor.
  • Test in realistic light and at an angle, not just head-on under a desk lamp.
  • Confirm the destination loads properly on mobile, and check people will have signal where they scan. A code in an underground station may scan fine and then load nothing.

Quick answers

Does a QR code expire? A static one does not — the data is in the pattern. Dynamic codes depend on a third-party redirect that can expire or be discontinued.

Can I put a logo in the middle? Yes, with error correction level H, keeping the logo under roughly 30% of the code’s area. Test after placing it.

Why won’t my code scan? In rough order of likelihood: no quiet zone, printed too small for the viewing distance, low contrast or an inverted colour scheme, or too much data crammed in.

What’s the smallest usable size? About 2 cm square for close-range print, larger if the code is dense. Scale up with viewing distance using the one-tenth rule.

PNG or SVG? SVG for anything going to print, since it scales without softening. PNG is fine for screens and email.

The takeaway

A QR code is just text wrapped in a robust encoding, and every scanning problem traces back to physics: too much data, modules too small, not enough contrast, or no quiet zone. Keep the URL short, use level M unless a logo forces H, leave the margin, size it for the real viewing distance, and scan a printed proof on a few different phones before the run goes out.

Tools mentioned in this guide

More developer guides

All guides
Developer What Is Base64 Encoding? A Complete Beginner's Guide Base64 turns binary data into safe, printable text. Learn how it works, when to use it, why it is not encryption, and how to encode or decode it in seconds. Developer URL Encoding Explained: Percent-Encoding, Query Strings and Common Bugs Why URLs break on spaces, ampersands and accents — and how percent-encoding fixes it. Covers encodeURI vs encodeURIComponent, + vs %20, and double encoding. Developer MD5 vs SHA-256: Which Hash Function Should You Use? MD5 is fast but broken; SHA-256 is the sensible default. Learn how hash functions work, why hashing is not encryption, and how to hash passwords properly.