Notes › Resources › Barcodes for inventory labels: choosing between CODE128 and EAN-13

Barcodes for inventory labels: choosing between CODE128 and EAN-13

I once helped a friend label more than two thousand bin locations in his small warehouse. After printing the first version I went round with a scanner, and three out of ten would not scan. There was an uglier problem too: he supplies a chain store, and the store's POS system rejected the labels outright with "this barcode does not resolve to a product". Until then I thought a barcode was just digits drawn as black and white bars. After doing the job I understood that whether it works depends on two completely separate things: whether the symbology is right, and whether you have the right to invent that number yourself.

First, work out who is going to scan it

That is the first thing those two thousand labels taught me. A code that only circulates inside your own stockroom and your own asset register can be numbered however you like, and it is scanned by your own equipment, so the choice comes down to two things: does it need letters, does it need a decimal point. A code that has to enter someone else's retail system is different; its number is global, and the digits the POS system reads must map to a manufacturer code you have registered. In that case the question is not which symbology to pick but whether you hold a legitimate number at all.

In Barcode Generator there are just these three mainstream symbologies to choose from: CODE128, EAN-13 and CODE39. Bar width can be set from 1 to 5 px and height from 40 to 200 px, foreground and background colours are selectable, the quiet zone and the text line under the barcode can each be switched on or off, and the output is a PNG.

Character ranges and check digits for the three symbologies

SymbologyCharacters it can encodeLengthCheck digitWhat I used it for
CODE128Printable ASCII 32 to 126, 95 characters in allVariableYes, modulo 103, appended by the encoderBin locations and asset numbers with letters
EAN-13Digits 0 to 9 onlyFixed 13 digitsYes, the 13th digit is computed from the first 12 with weightsBarcodes on retail product packaging
CODE39Uppercase A to Z, digits 0 to 9, plus the space and symbols - . $ / + %, 43 characters in allVariableNo arithmetic check digit in the symbology itself; the start and stop characters provide self-checkingSerial numbers on instruments, where old scanners recognise nothing else

The column most easily overlooked in those three rows is CODE39. It has no built-in arithmetic check digit, and some scanners or systems require an extra modulo 43 check character, which is a setting rather than part of the symbology. CODE39 also has an extended mode, where lowercase letters and symbols have to be built from pairs of characters, making the same content considerably longer than CODE128. When I run into old equipment that only reads CODE39, I first check whether extended mode and the check character are switched on; otherwise the labels it prints will not scan anywhere else.

If you need the full character set and a short code, CODE128 is usually the best answer, and that is why I switched symbologies for the bin labels: for the same number, the extended CODE39 form takes twice the width.

Working out an EAN-13 check digit by hand

At first I did not know the 13th digit was computed. I made up a string, typed it in, and the scanner threw an error; I assumed it was a printing problem. The algorithm is not complicated, so here is the working, in case you want to check it yourself.

Take a 12-digit string I made up on the spot, 690123456789 (this is a practice number, not the registered number of any real product). Counting from the left, add digits 1, 3, 5, 7, 9 and 11: 6+0+2+4+6+8=26. Add digits 2, 4, 6, 8, 10 and 12: 9+1+3+5+7+9=34, and that sum is multiplied by 3 to give 102. The two parts together are 26+102=128; the units digit is 8, and 10 minus 8 gives 2, so the check digit is 2 and the full barcode is 6901234567892. If the units digit happens to be 0, the check digit is 0, not 10.

Check with another set: the 12 digits 123456789012. The odd positions sum to 1+3+5+7+9+1=26 and the even positions to 2+4+6+8+0+2=22; 22 times 3 is 66, 26+66=92, the units digit is 2, 10 minus 2 gives 8, so the full code is 1234567890128. After working it twice I believed that "tick EAN-13 in the generator and it fills in the check digit for you". Get one digit among the first 12 wrong and the check digit no longer matches, so the scanner refuses to read it. That is protection, not a defect.

The prefix is not yours to invent

Those 13 digits are not a free number space. They split into a prefix, a manufacturer code, an item reference and a check digit, and the prefix part has to sit inside the GS1 system; a manufacturer identification code has to be applied for from the relevant issuing body. The familiar 690 to 699 ranges in China belong to the blocks allocated to Chinese manufacturers within that system. Make up a 690 number without registering and it scans as someone else's product; inside a retail system that is a collision, and being rejected is the mildest outcome my friend ran into. If you really need to go down this road, the correct move is to apply, not to fudge something with a generator.

If it is purely an internal number, my advice is blunt: do not use EAN-13. It holds digits only and is locked to 13 digits, so a code like "Shelf A - level 3" with letters in it will not fit at all.

Scanning depends on the printing, not just the encoding

Those three unreadable labels were a purely physical problem. A barcode reader measures the width of the black and white bars, and bar width in pixels times the printer's dot pitch gives the actual module width: on a 203 dpi thermal printer one dot is about 0.125 mm, so my 3-pixel bar width came out at about 0.375 mm; print the same image at 300 dpi and 3 pixels shrink to about 0.254 mm; at 600 dpi it is only about 0.127 mm. Thermal printing also bleeds sideways on fine lines, eating a little of the white bar, until the decoder cannot tell one module from two. I later moved the internal labels to a 4-pixel bar width, reprinted, and all three scanned.

Two more I learned the hard way. First, leave white space on both sides, the quiet zone: the scanner uses that blank stretch to decide where the barcode begins, and I had turned the quiet zone off early on to save label stock, which is why nothing read. Second, colour: the tool lets you change foreground and background, but a typical scanner uses red light, and red looks almost as bright as white to it, so do not try red backgrounds or red bars. Strong light-dark contrast is enough; it does not have to be pure black.

I do not sign off on a print run by eye. I photograph a label, upload it to Barcode Decoder and read it back; only when the digits come back exactly does it count. If the payload is a long stretch of text, or the scan has to open a URL directly, a linear barcode is the wrong tool, and I switch to QR Code Generator for that.

Common questions

Q: A supermarket wants a barcode from me. Can I just generate one myself?

No. EAN-13 number blocks are allocated through the GS1 system, and a made-up number will collide with a real product. A generator can compute a valid check digit, but it cannot compute a valid manufacturer code.

Q: My warehouse codes contain letters. Which symbology should I use?

CODE128. EAN-13 holds 13 digits and nothing else; CODE39 can hold letters but only uppercase plus seven symbols, and the same content takes more width.

Q: Why does my barcode print but not scan?

The causes I have run into, in order of likelihood: bar width too thin for the printer's precision, no quiet zone on either side, blurry edges after scaling, and colour contrast that fails under red light. Add one step to the bar width, turn the quiet zone on, and print a test label.

Q: What happens if the check digit is wrong?

The scanner usually refuses to read at all rather than reading a different number, because the check digit exists to catch exactly that error. When you enter an EAN-13 by hand, one wrong digit in the first 12 and the check digit no longer matches.

Q: Can CODE39 and CODE128 be mixed on the same batch of labels?

Yes, but it depends on the scanner's settings and what it is set up to recognise. My rule is one symbology per system: the troubleshooting cost of mixing them far outweighs the width you save.

Back to those two thousand labels. In the end every internal bin label moved to CODE128, 4-pixel bar width, quiet zone on, with sample decodes after printing. The batch going to the chain store did not keep using made-up numbers; we waited for the manufacturer code to be approved and reprinted. The rule is clear enough: for codes that only circulate at home, choose the symbology by character set and width; for codes that have to leave and enter someone else's POS system, settle who owns the number first, and talk about generators after that.

📎 Related articles

SOS is 9 tones, the full alphabet is 104: how Morse timing is calculated 2026-10-21 What does a weight of 30 mean on a spinner? Sector angles and draws with or without replacement 2026-10-21 Why white text on gradients is hard to read: checking WCAG contrast at every stop 2026-10-21 Enlarging old photos without blur: how much detail enhancement can recover 2026-10-15 Making a perler bead pattern: turning a photo into a colour chart and grid 2026-10-15