Project Nayuki

Creating a QR Code step by step

This JavaScript demo application visualizes in detailed steps, how a text string is encoded into a QR Code barcode symbol. The content of this page essentially explains and justifies how my QR Code generator library works internally.

User input

Error correction level:
(between 1 and 40)
(−1 for automatic, 0 to 7 for manual)

QR Code output

Step-by-step process

Show/hide each step:

0. Analyze Unicode characters

Number of code points in the input text string:

Details of each character:

Index Char CP hex NM AM BM KM

Can every character be encoded in:

Mode Encodable

Chosen segment mode to encode all characters:

1. Create data segment

Convert each character to bits. For numeric and alphanumeric modes, consecutive characters are grouped together before being encoded into bits. For byte mode, a character produces either 8, 16, 24, or 32 bits.

Index Char Values (hex) Value Combined Bits

The created single segment:

  • Mode:
  • Count:
  • Data:

(This demo program always creates a single segment for simplicity. But it is possible to segment the text optimally to minimize the total bit length.)

2. Fit to version number

Total bit length needed to represent the list of segments, depending on version:

Range Num bits Num codewords
Version 1 ~ 9
Version 10 ~ 26
Version 27 ~ 40

(Note: A codeword is defined as 8 bits, also known as a byte.)

QR Code capacity of data codewords per version and error correction level, and whether the data fits (green/red background):


Chosen version number:

3. Concatenate segments, add padding, make codewords

Join a variety of bit strings together:

Item Bit data Num bits Sum bits


  • The segment mode is always a 4-bit field.

  • The character count’s field width depends on the mode and version.

  • The terminator is normally four “0” bits, but fewer if the data codeword capacity is reached.

  • The bit padding is between zero to seven “0” bits, to fill all unused bits in the last byte.

  • The byte padding consists of alternating (hexadecimal) EC and 11 until the capacity is reached.

The entire sequence of data bits:

The entire sequence of data codeword bytes (by splitting the bit string into groups of 8 bits), displayed in hexadecimal:

4. Split blocks, add ECC, interleave

Statistics about all blocks:

Number of data codewords:
Number of blocks:
Data codewords per short block:
Data codewords per long block:
ECC codewords per any block:
Number of short blocks:
Number of long blocks:

Split the sequence of data codewords (green background) into short and long blocks; then for each block, compute the ECC codewords (blue) and append them to the end of the block:

Block index

(Note: The math behind computing the Reed–Solomon error correction codes is omitted because it is long, tedious, and not very interesting.)

The final sequence of codewords formed by interleaving data/ECC codewords from different blocks:

The final sequence of bits to draw in the zigzag scan:

5. Draw fixed patterns

Draw the horizontal and vertical timing patterns (on both row 6 and column 6, counting from 0 starting at the top left corner):

Draw finder patterns on the three corners, each of which is 8×8 including the separator, overwriting some timing modules:

Draw the grid of alignment patterns, each of which is 5×5, but skipping the three finder corners, and ones that overlap timing modules blend in perfectly:

Draw temporary dummy format bits (adjacent to the finders):

Draw the two 6×3 version information blocks (adjacent to the finders):

6. Draw codewords and remainder

Compute the zigzag scan (which starts from the bottom right corner) to visit all unfilled modules (i.e. skipping function modules):

Draw data/ECC modules according to the zigzag scan order and bit values from the final sequence of codewords:

(For example, the codeword byte C5 (hex) is 11000101 in binary, and produces the sequence of modules [dark, dark, light, light, light, dark, light, dark].)

7. Try applying each mask


The mask pattern (only affects non-function modules):

XOR the mask to the modules of data, ECC, and remainder:

Draw the actual format bits (adjacent to the finders):

8. Find penalty patterns

Horizontal runs of same color modules (each at least 5 long):

Vertical runs of same color modules (each at least 5 long):

2×2 boxes of same color modules:

Horizontal finder-like patterns:

Vertical finder-like patterns:

Balance of dark/light modules:

Side length:
Total modules:
Light modules:
Dark modules:
Proportion dark:
Deviation from half:

9. Calculate penalty points, select best mask

Mask RunP BoxP FindP BalP TotalP

Lowest total penalty points: Mask pattern

How penalties are calculated:

  • RunP: 3 points for each 5-module linear run of the same color, 4 points for each 6-module run, 5 points for each 7-module run, 6 points for each 8-module run, etc. Runs cannot overlap.

  • BoxP: 3 points for each 2×2 box of the same color. Boxes can overlap.

  • FindP: 40 points for each finder-like pattern. Finder patterns can overlap.

  • BalP: 0 points if the proportion of dark modules is in the range [45%, 55%]; 10 points if within [40%, 60%]; 20 points if within [35%, 65%]; 30 points if within [30%, 70%]; etc.

This web application’s source TypeScript code (file 0, file 1) and compiled JavaScript code are available for viewing.

More info