Two QR Codes on One Label Without Either One Failing — featured illustration
Best Practices

Two QR Codes on One Label Without Either One Failing

7 min read
Create a QR code

A shipping label goes out with two codes on it, one for the carrier and one for the warehouse, twelve millimetres apart. The handheld scanner reads whichever it finds first, and which one that is depends on how the operator holds it. Parcels start getting booked against the wrong record, and nobody works out why for three weeks.

Two codes on one piece of paper is a normal requirement. It is also the situation where readers behave least predictably, because nothing in the QR specification says anything at all about what to do when there are two.

A reader sees a frame, not a label

A decoder does not know your label exists. It gets a rectangular image from a camera and searches it for finder patterns: the run-length signature of dark, light, dark, light, dark in proportions near 1:1:3:1:1, found by sweeping scan lines across the frame.

With two codes in the frame, it finds six finder patterns. What happens next is entirely up to the software. It may group them into two symbols and return both, group them into two and return one, or group them wrongly and return nothing. Grouping is geometry: three finders sitting at the corners of a plausible square at a consistent module pitch belong to one symbol. Put two codes close together, at the same size, and two of those six candidates can end up as close to each other as they are to their own partners.

That is the failure worth engineering against. Not the nuisance case where the reader picked the wrong code, but the case where it assembled a square out of finders belonging to two different codes, which produces a read of nothing at all from a label on which both codes are perfect.

How far apart is far enough

Each code needs its full four-module margin on every side, and that margin belongs to one code rather than being shared with its neighbour. So the honest minimum gap between two codes is the sum of both margins, eight modules of the larger code, measured between the outermost dark modules.

Modules, not millimetres, as always. A 33-module code printed 30 mm wide has modules near 0.9 mm, so eight of them is roughly 7.3 mm. The same code at 15 mm wide needs half that. Counting in modules rather than millimetres is the whole discipline here, and it is why a gap that worked on a poster fails on a sticker.

Eight modules is the floor, and in practice give it more. Grouping ambiguity gets worse as the codes get closer relative to their own size, so a generous gap is what keeps the two clusters of finder patterns distinguishable. And a reader held at an angle sees a compressed, sheared image in which a marginal gap narrows further.

If the label has room, stack the codes on separate lines rather than placing them side by side, with text in between. Text in the gap is not a margin violation as long as each code keeps its own four modules clear, and a line of type separates the two codes better than empty space does, because it also tells a person which code is which.

Some readers take the nearest, some take the first found

There is no standard, and the behaviour splits by application rather than by platform.

Phone camera apps generally aim for one result and pick by prominence: the largest candidate, the most central one, or the first detected, which on a handheld camera is usually whichever code is nearest the middle of the viewfinder. Some newer camera apps detect several codes at once and draw a tappable marker on each, which converts the ambiguity into a choice the person makes.

Dedicated scanner apps and hardware imagers behave differently. Many return the first symbol that decodes cleanly, and the scan order depends on how the image is swept, so the answer changes with the angle of the device. Others have a multi-code or batch mode that reads everything in frame and returns a list, and it usually ships disabled because it costs decode time on every frame.

Two conclusions follow. You cannot control which code a given reader picks, so never design a label where picking the wrong one causes harm. And if two codes must coexist while serving different readers, buy separation with physical distance instead of relying on any reader's preference.

When two codes are the right answer

There are cases where two is correct and one would be worse.

  • Two audiences with different readers. A retail scanner expecting one payload convention and a shopper expecting a link are not the same job, and merging them serves neither.
  • A link plus a self-contained payload. A wifi code that works with no signal, next to a link to the house rules, which needs one. What finishes on the device and what needs a network is the deciding line.
  • A code plus a serial. One code identifies the unit and the other points at the manual. Asset labels often carry both, because the serial has to be readable by a system that has never heard of your web page.
  • Two languages, sometimes. Sometimes.

That last one deserves a paragraph of its own, because it is the most common reason people reach for two codes and usually the wrong one.

Two languages is usually one code

A code per language looks considerate and costs you the thing that makes codes useful. Every printed piece now carries a fixed, unmeasured, uneditable split of your audience, and the split is wrong anyway: visitors do not sort themselves neatly onto two labels, and a French speaker faced with a French code and an English code will scan whichever one is nearer their hand.

One code pointing at a page that offers both languages, or that reads the phone's own language preference and offers a switch, does the same job with half the artwork and gives you one set of counts instead of two. Building multilingual experiences goes through the approaches; the short version is that the routing belongs in the page, not on the label.

The exception is where the two destinations are genuinely different things rather than translations of one thing: a staff form and a customer menu, an internal ticket and a public tracking page. Those are two codes because they are two purposes.

A person cannot tell two codes apart

This is the part that gets left out. Two identical black squares carry no information about which is which. A sighted reader in good light cannot distinguish them, and somebody using a screen reader on a digital version of the label gets nothing at all unless a human wrote it down.

So label them, in words, beside each code, at a size a person can read from where they will be standing.

  • Use a noun, not an instruction. Menu and Wine list beat Scan here and Scan me, which are indistinguishable from each other.
  • Put the label on the same side of each code, consistently, so the pairing is obvious at a glance.
  • On screens and in email, give each image alt text naming its destination rather than the words QR code, and include the real links as text. Alt text for code images has the specifics.
  • If one code is for staff and one for the public, say so. A line reading Staff only prevents more wrong scans than any amount of separation.

The test

Print the label at final size and scan it eight times: twice with a phone camera held centred, twice with one code at the edge of the frame, twice at roughly thirty degrees off perpendicular, and twice on whatever dedicated scanner the label will actually meet. Write down which code answered each time.

If you get both codes across those eight attempts, the separation is working and the printed labels are doing their job. If any attempt returns nothing at all, the gap is too small and finders are being grouped wrongly. Widen it in module counts rather than by eye, and check the placement and size rules against the distance people will really be standing at. If the two destinations ever need to swap, that is an argument for a dynamic code on both, since the labels are the expensive part.

Share this article