Skip to main content

QR Code Encoding Modes Explained

Why is your QR code so big? The answer is almost always encoding mode. Here is the plain-English version, written for the people who own packaging — not the people who write QR libraries.

The thirty-second version

Inside every QR code, the data you encode is squeezed through one of four compression schemes — numeric, alphanumeric, byte, or kanji. Each one packs characters at a different bit cost. Pick the right input, and your QR code shrinks by an entire version. Pick the wrong input, and you pay for that mistake every time the package goes through the press.

The single biggest mistake in real-world packaging is publishing a lowercase URL. It silently forces byte mode and inflates every QR symbol you ship.

Want to see it for yourself? Paste a URL into the QR Code Inspector — it shows the per-segment encoding-mode breakdown, the version, and concrete recommendations for shrinking the symbol.

What an encoding mode actually is

A QR code stores binary data — ones and zeros painted onto a grid of light and dark modules. Before that data goes onto the grid, the encoder has to translate your input string into bits. The QR specification (ISO/IEC 18004) defines four ways to do that translation, each tuned to a different kind of input:

  • Numeric — digits 0–9 only. Three digits pack into 10 bits (≈3.33 bits per character). The cheapest mode by far. A 14-digit GTIN costs about 47 bits.
  • Alphanumeric — A 45-character set: A–Z, 0–9, space, and the punctuation $ % * + - . / :. Two characters pack into 11 bits (≈5.5 bits per character). Notice the absence of lowercase letters and the absence of common URL characters like ? = & # _.
  • Byte — Any single-byte value (typically UTF-8). Eight bits per character. The fallback used whenever your input contains anything outside the alphanumeric 45-character set.
  • Kanji — JIS X 0208 Japanese characters, encoded as 13 bits per character. About half the bit cost of representing the same characters in UTF-8 byte mode. Irrelevant outside Japanese-market packaging.

The bit cost matters because every QR version has a fixed capacity in bits, scaling with the module count and the error-correction level. Cheaper bits means more characters fit in the same symbol — or, conversely, the same characters fit into a smaller symbol.

Why uppercase URLs are smaller

This is the single most important practical takeaway in this article, so it gets its own section.

The QR alphanumeric character set has no lowercase letters. None. The instant your URL contains any lowercase letter, the encoder has to switch from alphanumeric mode to byte mode for that segment — and once in byte mode, every character (uppercase or otherwise) inside that segment costs 8 bits instead of 5.5.

For a typical 35-character GS1 Digital Link URL, the difference between encoding the whole thing alphanumeric and encoding the whole thing byte is about 90 bits. That gap is frequently the difference between QR Version 3 (29 × 29 modules) and QR Version 4 (33 × 33 modules) — which translates to ~4 mm of extra physical print size at the GS1 minimum X-dimension.

Crucially, uppercasing the scheme and host of a URL is semantically safe. RFC 3986 declares the scheme and authority components case-insensitive — HTTPS://EXAMPLE.COM/ resolves identically to https://example.com/. The path and query components are case-sensitive, so leave those alone. The pattern is:

HTTPS://EXAMPLE.COM/01/00614141123452
^^^^^^^^^^^^^^^^^^^^             ^^^^^^^^^^^^^^^^^
alphanumeric (cheap)             numeric (cheapest)

When the encoder sees that input, it splits the string into segments — alphanumeric for the scheme/host/AI prefix, numeric for the GTIN — and emits the cheapest possible bit stream for each. This is called mixed-mode encoding, and it is where the real savings come from.

Mixed-mode encoding: the part most generators skip

A naïve QR generator picks a single encoding mode for the entire input string. Hand it your URL, it scans the input, sees a lowercase letter or a question mark, decides "byte mode", and encodes the whole thing at 8 bits per character.

A serious QR generator does something smarter. It runs a dynamic-programming optimizer that walks the input character by character and decides — at every position — which mode is cheapest given the per-mode bit cost and a small fixed cost for switching modes. The output is a sequence of mode segments, each emitted at its own bit-rate, joined by tiny mode-switch markers.

On a typical Digital Link URL, the optimizer produces three segments:

  1. An alphanumeric segment for the scheme + host + AI path prefix (HTTPS://EXAMPLE.COM/01/).
  2. A numeric segment for the GTIN itself (00614141123452).
  3. Optionally, a byte segment for any case-sensitive query parameters or non-alphanumeric punctuation that follows.

The bit savings from mode-switching mid-symbol routinely shave one full version off the resulting QR. That is roughly the difference between a 19 mm sticker and a 22 mm sticker at GS1-minimum sizing.

How Zint optimises GS1 Digital Links

Closient generates QR codes through Zint, an open-source barcode library that ships with mixed-mode optimisation on by default. The optimiser is mode-aware down to the per-character level, and Zint's GS1-specific input parser hints the encoder to keep AI-delimited numeric segments together so they encode as numeric rather than getting fragmented across mode boundaries.

In practice, this means a Closient-generated QR for a 14-digit GTIN on a short brand-owned resolver domain typically lands at QR Version 3 — about 18 mm at GS1 minimum X-dimension. The same input run through a less aggressive encoder often comes out at Version 4 or 5, which costs additional millimetres on every product label you ship.

Use the QR Inspector to verify what mode breakdown your URL actually got: it surfaces the per-segment mode list directly from the Zint encoder pipeline, with capacity-utilisation percentages and concrete "uppercase this" recommendations.

Worked example: the same URL, encoded three ways

Take a 36-character GS1 Digital Link URL pointing at a GTIN. Same data, three input shapes:

Input Mode breakdown QR version
https://example.com/01/00614141123452 Byte (whole string) V4 (33 × 33)
HTTPS://EXAMPLE.COM/01/00614141123452 Alphanumeric → Numeric V3 (29 × 29)
HTTPS://EXAMPLE.COM/01/00614141123452?lot=abc Alphanumeric → Numeric → Byte V4 (33 × 33)

Two takeaways. First, uppercasing the scheme and host saves a full version. Second, any lowercase qualifier — a lot code, a serial, a query string — drops the trailing segment into byte mode. If the lot code happens to be all-uppercase digits and letters, the encoder keeps it in alphanumeric mode and you skip the version bump.

What this means for packaging

If you control the URL pattern your QR codes encode — and as a brand owner, you do — design it for cheap encoding from day one:

  • Always emit scheme and host in uppercase (HTTPS://EXAMPLE.COM/).
  • Keep the resolver domain short. Each character outside the GTIN costs proportionally more than each character inside it.
  • Use uppercase alphanumeric for any GS1 AI value where the spec allows it (lot codes, serials). Avoid lowercase letters and unusual punctuation in lot patterns.
  • Push everything that has to be byte-encoded — query strings, fragments — to the very end of the URL, so the optimiser can keep the prefix in alphanumeric mode for as long as possible.
  • Verify the actual mode breakdown with the inspector before going to print. Do not trust that the encoder "probably did the right thing".

Frequently asked

These are the conversational chains people walk through when they realise their QR symbol is a version too big.

Why is my QR code so big?

Almost always because the encoder fell back to byte mode when it could have used alphanumeric. The fix is to inspect the per-segment mode breakdown, find the segment that fell back, and rewrite that part of the URL in uppercase.

Does case matter?

For the encoded data: yes, completely. Uppercase belongs to alphanumeric mode (5.5 bits/char); lowercase forces byte mode (8 bits/char). For the URL semantics: scheme and host are case-insensitive (RFC 3986), so uppercasing them is safe. Path and query are case-sensitive — leave those alone.

Should I use numeric mode for my GTIN?

You don't pick the mode — the encoder does. As long as the GTIN is encoded as a continuous run of digits with no embedded letters, a competent optimiser will keep it in numeric mode automatically. Verify with the inspector if you're not sure.

Why does my QR have multiple modes inside it?

That is mixed-mode encoding doing its job. The encoder is using cheap modes where it can and falling back to expensive modes only where it must. A multi-mode QR is almost always smaller than a single-mode QR for URL-style input.

Do all generators do mixed-mode optimisation?

No. Many cheap online generators emit byte mode for the whole input. The fix is to use a generator that supports per-segment optimisation — Zint, and the Closient QR pipeline that wraps it, do this by default.

How does this interact with error correction?

Encoding mode determines how many bits your data takes. Error-correction level (L/M/Q/H) determines how much of the QR's total bit budget is reserved for recovery codewords. They compose multiplicatively: cheap modes plus low ECC fits into a tiny QR; expensive modes plus high ECC blows up the version. Pick GS1's recommended ECC M for retail packaging and rely on mixed-mode encoding to do the rest.

Tools that show the mode breakdown

  • QR Code Inspector — deep-analysis breakdown including per-segment mode list, version, and concrete optimisation recommendations
  • Print Size Calculator — see how the version your encoding produces translates into physical mm of print
  • QR Generator — compose a Digital Link, render the QR, verify the result fits your packaging real estate

Further reading

Bit cost per character

Numeric~3.33 bits
Alphanumeric~5.5 bits
Byte8 bits
Kanji13 bits

Lower is better. The cheapest viable mode for each input segment determines the resulting QR version.

The one thing

Uppercase the scheme and host of every URL you encode. HTTPS://EXAMPLE.COM/01/... routes identically to the lowercase version, but encodes in alphanumeric mode at 5.5 bits per character instead of byte mode at 8 — frequently saving a full QR version.

Generate, inspect, and resolve millions of GS1 Digital Link QR codes — without thinking about encoding modes.

See pricing