^BQ - QR Code Bar Code
The common two-dimensional matrix symbology. Its error correction and input mode are set by a prefix on the field data, not by the command.
^BQ prints a QR Code: a square matrix with position patterns at three corners,
so a scanner finds it at any angle. It is the two-dimensional symbology for a
label that a phone reads, and it tolerates damage better than ^BX Data Matrix
at the same size. Most of its configuration is not in the command. The
error-correction level and the input mode are a prefix on the field data.
Syntax
^BQo,m,g,e,kSupport
The command renders, with the caveat below.
Model 2 renders, with the error correction and input mode from the ^FD prefix. The renderer does not implement model 1, mixed mode and Kanji mode. Labelary does not implement them either, so there is no compatibility gap. The renderer parses the m model argument and ignores it. — not pinned by a test
Labelary renders this command.
Parameters
oBar code orientationoptional · one of a setFor backward compatibility only. Labelary documents N as the only accepted value.
- Default
- N
- Invalid value
- discarded, and the default applies. The renderer reports an unrecognized character, and uses
N. - Test coverage
- No documented value is exercised by a test (N). The invalid-value rule is not pinned by a test.
N- No rotation (default)
mModeloptional · integernot honoured by zpl.toolsQR Code model. Model 1 is the original specification, and it is deprecated. Use model 2.
- Default
- 2
- Accepted range
- 1 to 2
- Invalid value
- not documented, and we have not measured it. Labelary treats this as a discrete pair with its own messages. 0 resets to 2, 3 clamps to 2, and 1 gets a deprecation notice (measured 2026-07-12). The renderer accepts the value without validation and always encodes model 2.
- Test coverage
- No test at the minimum, maximum or one step outside the range.
gMagnificationoptional · integerModule size in dots. This argument is the only size control, since the ^BY module width has no effect on QR Code.
- Default
- 2
- Accepted range
- 1 to 100
- Invalid value
- clamped to the nearest allowed value. This range is asymmetric. 0 resets to the default of 2, while a value above 100 clamps to 100 (measured against Labelary 2026-07-12). The guide's stated maximum of 10 is not the real limit.
- Test coverage
- Bounds pinned: minimum (1), below the minimum (0), above the maximum (999). No test at the maximum. The invalid-value rule is not pinned by a test.
eError correction leveloptional · one of a setDefault error-correction level, for field data with no level prefix of its own.
- Default
- Q
- Invalid value
- discarded, and the default applies. An unrecognized level defaults to
Q. - Test coverage
- Values exercised: H. Not exercised: Q, M, L. The invalid-value rule is not pinned by a test.
H- Highest reliability, about 30% of codewords recoverable
Q- High reliability, about 25% (default)
M- Medium reliability, about 15%
L- Lower reliability, about 7%
kMask patternoptional · integerMask for the module grid.
- Default
- 7
- Accepted range
- 0 to 7
- Invalid value
- not possible — any value is accepted. Labelary reports no warning for values outside 0-7: 0, 8 and 15 are all silent (measured 2026-07-12). The renderer does not validate this argument.
- Test coverage
- Bounds pinned: above the maximum (8). No test at the minimum or maximum.
Behavior
The field-data prefix
The guide's syntax for the field data is an error-correction level, then an input mode, then a comma, then the payload:
^FD<level><mode>,<data>The level is one of H, Q, M or L, in decreasing order of recoverable
damage and increasing order of density. The mode is A for automatic or M for
manual. Under automatic input the encoder selects the character mode. Manual
input needs an explicit character mode immediately before the data:
Nfor numeric;Afor alphanumeric;Band a four-digit byte count for 8-bit data;Kfor Kanji.
^FDQA,0123456789ABCD is therefore automatic, and ^FDHM,N123456789012345 is
manual numeric at the highest error-correction level.
The prefix is not optional. We measured this against Labelary on 2026-07-30. The
encoder consumes the first two characters of the field data as the level and the
mode, whether or not they name a valid pair. ^FD12345 renders exactly the same
symbol as ^FDQA,345. A payload with no prefix therefore loses its first two
characters, silently and with no warning. Always write the prefix.
The e argument is only a default for data that carries no level of its own. Do
not depend on that state.
Symbol size
^BY has no effect on QR Code, so the magnification argument is the only size
control: it is the width of one module in dots. The encoder selects the version
and the mask from the payload and the error-correction level. A longer payload
therefore gives a denser grid at the same magnification and not a larger symbol.
Use model 2. Model 1 is the original specification and is deprecated, and the
renderer does not encode it whatever the m argument says.
The guide documents mixed mode, the D switch that splits one message across
several symbols with a parity byte. The renderer implements neither mixed mode
nor Kanji mode. Labelary implements neither, so a format that works there works
here.
Tested behavior
Differences from the specification
Labelary against the ZPL II guide
Where Labelary — our compatibility target — behaves differently from the printed specification.
- The guide gives the magnification range as 1-10. Labelary accepts up to 100 and scales linearly throughout (measured 2026-07-12); the renderer follows Labelary. — pinned by
test_bq_magnification_above_max_clamps - Labelary raises the error-correction level to the highest one the chosen version still holds, so
LA,LLPpalletrenders as version 1-Q (measured 2026-08-17); the renderer follows Labelary. — not pinned by a test - Labelary cuts the payload into segments by Okapi Barcode's run-length heuristic rather than the shortest encoding. One measured payload costs 826 bits where 808 would do (2026-08-17). The renderer follows Labelary. — not pinned by a test
- The
^BYbar-code height is the gap Labelary leaves between an^FOorigin and the symbol's top edge, at least one dot (measured 2026-08-17); the renderer follows Labelary. — not pinned by a test
zpl.tools against the ZPL II guide
Where our renderer behaves differently from the specification.
- The renderer never encodes model 1, whatever
msays. — not pinned by a test - The renderer accepts
R,IandBin the orientation argument. It leaves the symbol upright and turns only the field box, which is what Labelary does; the guide acceptsNonly. — not pinned by a test
zpl.tools against Labelary
Where our output differs from Labelary for the same input. These are the differences that break a migration.
- Labelary ignores the
eargument and takes the level from the field-data prefix alone (measured 2026-08-17). The renderer takeseas the level for data with no prefix. — not pinned by a test - Labelary ignores the
kmask argument and always evaluates all eight masks (measured 2026-08-17). The renderer draws the requested mask. — not pinned by a test - Labelary drops the first three characters of the field data whether or not they are a valid prefix, and defaults to level
M(measured 2026-08-17). The renderer encodes unprefixed data whole. — not pinned by a test
Example
A URL at high reliability with automatic input mode. The QA, prefix is the part to copy — drop it and the first two characters of the URL are read as the level and mode instead of being encoded.
^XA
^FO50,50
^BQN,2,6
^FDQA,https://example.com^FS
^XZ
Related commands
^BXData Matrix Bar CodeCompact two-dimensional symbology used for small-part marking and GS1 DataMatrix.^FDField DataSupplies the text or barcode content of the field.^FOField OriginSets the top-left corner of the next field.^FTField TypesetPositions the next field by its text baseline rather than its top edge.