Extract QR codes and barcodes, decoded not guessed

A model reading a QR code from pixels is pattern matching on a grid and will return a plausible wrong payload. Veralens decodes symbols with a real decoder, and returns null when there is none.

5 min read

Ask a vision model what a QR code says and it will tell you. That answer is a guess.

A QR code is a dense grid of black and white modules encoding bytes through masking, interleaving and Reed-Solomon error correction. Reading it is a decoding problem, not a perception problem. A model looking at that grid is doing pattern completion on something that is not text, and it will produce a string that looks like a plausible payload: a URL of about the right shape, a fiscal code of about the right length, an EAN with the right digit count and the wrong digits.

The same applies to linear barcodes, where the failure is more insidious because a wrong digit in the middle of an EAN still looks like an EAN.

What Veralens does

The codes are decoded, not read. Every image and page you send goes through a real barcode decoder before extraction happens. Whatever the decoder finds is the value that ends up in your field. The model never supplies it.

That gives you three properties that matter:

The payload is exact or it is absent. A decoder either resolves the symbol or it does not. There is no halfway, and there is no plausible approximation.

Error correction actually works. QR codes carry Reed-Solomon redundancy specifically so that damaged, partially obscured or badly printed symbols still resolve. A decoder uses it. A model looking at the picture cannot.

No code means null. If there is no readable symbol on the page, the field comes back empty rather than filled with something that looks like a payload. This is the property that matters most, because a fabricated code is undetectable downstream.

Supported: QR, Micro QR, and the common linear families such as EAN, UPC, Code 128, Code 39 and ITF.

How to ask for one

Add format: "qrcode" or format: "barcode" to a string field:

json
{
  "type": "object",
  "properties": {
    "supplier_name": { "type": "string" },
    "total":         { "type": "number", "multipleOf": 0.01 },
    "qr_code":       { "type": "string", "format": "qrcode" },
    "product_ean":   { "type": "string", "format": "barcode" }
  },
  "required": ["total"]
}
json
{
  "supplier_name": "Padaria Central",
  "total": 24.9,
  "qr_code": "A:509442100*B:123456789*C:PT*D:FT*E:N*F:20260314*G:FT AB2026/0001*H:0*I1:PT*I7:20.24*I8:4.66*N:4.66*O:24.90*Q:kKzD*R:2609",
  "product_ean": "5601234567890"
}

That QR payload is the real content of a Portuguese fiscal QR code, decoded from the symbol. A model asked to read it from the pixels would produce something with the right punctuation and the wrong numbers.

Where this actually bites

Fiscal and tax QR codes. Portugal, Spain, Italy, India and a growing list of countries now print a mandatory QR carrying the invoice's tax data. That payload is the authoritative record, more trustworthy than the printed figures, and it is machine readable. Reading it wrong is worse than not reading it.

Payment codes. EPC and Pix QR codes carry an IBAN or key and an amount. There is no acceptable error rate on a field that decides where money goes.

Product identifiers. An EAN or UPC is a database key. One wrong digit is a different product, or no product.

Tracking and asset labels. Same story: the code is an identifier and a near miss is not a partial answer, it is a wrong one.

In all four cases the code exists precisely because a machine is supposed to read it exactly. Handing that to a model that estimates is throwing away the reason the code is printed.

Verify it yourself in one minute

This is the easiest claim on our site to check, and we would rather you did:

  1. Take any document with a QR code or a barcode.
  2. Scan it with your phone and copy what the phone gives you.
  3. Send the same document with a format: "qrcode" field.
  4. Compare the strings.

They should be identical, character for character. Then try the reverse test that matters more: send a document with no code and confirm the field comes back null rather than something plausible.

The quickstart has you sending the first one in a few minutes.

Try it on your own documents

Add funds from $5, create a key, and send your first document. Every job reports exactly what it cost.

Start extracting

Keep reading