ZATCA QR code explained: the 9 TLV fields, Phase 1 vs Phase 2, and how to check one
By Zain Abbas, Kodenova · Updated
What the QR code actually is
The QR code on a Saudi e-invoice is not a link and not a picture of the invoice. It is a short block of data, encoded in Base64, that a phone can read without going online.
The data inside uses a format called TLV: Tag, Length, Value. Every field is written as three parts, one after the other:
- Tag: one byte that says which field this is (1 for seller name, 2 for VAT number, and so on).
- Length: one byte that says how many bytes the value takes.
- Value: the field itself, encoded in UTF-8.
All fields are joined with no spaces or separators, and the whole byte string is then Base64 encoded. ZATCA’s technical guideline sets a limit of 700 characters for the final Base64 string.
The 9 TLV fields
| Tag | Field | Example value | Phase |
|---|---|---|---|
| 1 | Seller name | Al Noor Trading | Phase 1 and 2 |
| 2 | Seller VAT registration number | 300000000000003 | Phase 1 and 2 |
| 3 | Invoice timestamp (date and time) | 2026-10-16T10:15:00Z | Phase 1 and 2 |
| 4 | Invoice total with VAT | 1150.00 | Phase 1 and 2 |
| 5 | VAT total | 150.00 | Phase 1 and 2 |
| 6 | Hash of the XML invoice | SHA-256 hash | Phase 2 |
| 7 | ECDSA signature of the hash | cryptographic value | Phase 2 |
| 8 | ECDSA public key | cryptographic value | Phase 2 |
| 9 | ZATCA’s signature over the stamp’s public key | cryptographic value | Phase 2, simplified invoices and their notes only |
Tags 1 to 5 are plain text you can read. Tags 6 to 9 are cryptographic data, so a decoder shows them as encoded strings, not words.
The invoice hash in tag 6 is a SHA-256 hash of the XML invoice. ZATCA’s security standard explains that the hash excludes the UBL extensions, the signature block and the QR element itself, which makes sense: the QR cannot contain a hash of itself.
Phase 1 vs Phase 2
ZATCA rolled out e-invoicing in two phases, and the QR code changed with them.
Phase 1 (generation) started on 4 December 2021. Invoices had to be produced by a compliant system, and simplified tax invoices (B2C) had to carry a QR code with the five basic fields. ZATCA’s Detailed Guidelines say plainly that a QR code was not mandated on standard tax invoices (B2B) in this phase.
Phase 2 (integration) started on 1 January 2023 and is being applied in waves. Taxpayers are brought in by revenue threshold. If your company is in the latest group, see our note on Wave 25 for SAP Business One. In Phase 2 the QR code gains tags 6 to 9, and the rules depend on the invoice type:
| Standard tax invoice (B2B) | Simplified tax invoice (B2C) | |
|---|---|---|
| ZATCA flow | Clearance, before the invoice goes to the buyer | Reporting, within 24 hours of issue |
| Who stamps the invoice | ZATCA, during clearance | Your system, with its own CSID |
| QR code | Added or updated by ZATCA in the clearance response | Generated by your system with all 9 tags |
| Tag 9 | Not used | Required |
The practical point for B2B: your printed or PDF invoice should use the QR code that comes back from ZATCA after clearance, not one your system made before sending. For B2C, your system builds the full QR itself at the moment of sale.
A worked example
Here is a Phase 1 style QR string for an invoice of SAR 1,000 plus 15% VAT, built from the example values in the table above:
AQ9BbCBOb29yIFRyYWRpbmcCDzMwMDAwMDAwMDAwMDAwMwMUMjAyNi0xMC0xNlQxMDoxNTowMFoEBzExNTAuMDAFBjE1MC4wMA==
If you decode the first bytes you see 01 0F followed by the seller name. 01 is tag 1. 0F is 15 in hex, the number of bytes in “Al Noor Trading”. Then comes 02 0F and the 15-digit VAT number, and so on through tag 5.
Paste that string into our free ZATCA QR code decoder and you will see the five fields laid out one by one.
How to check a QR code on your invoice
Use this when a customer complains that their scanner shows “invalid QR”, or when you test a new invoice layout.
- Get the raw string. Scan the printed QR with any scanner app, or copy the value stored on the invoice record in your ERP.
- Decode it. Run it through a TLV decoder. If the decoder fails at once, the string is probably not Base64, or extra characters were added (spaces, line breaks, a URL prefix).
- Compare tags 1 to 5 with the invoice. Seller name and VAT number must match your VAT registration. Tag 4 must equal the invoice total including VAT. Tag 5 must equal the total VAT on the invoice.
- Check the timestamp. Tag 3 should match the invoice issue date and time. A timestamp from a different day usually means the QR was built from the wrong field.
- Count the tags. A Phase 2 simplified invoice should show 9 tags. A cleared standard invoice should carry the QR returned by ZATCA. If you see only 5 tags on a Phase 2 invoice, your layout is printing an old Phase 1 value.
- Check the length. The Base64 string should be at most 700 characters.
Decoding confirms the structure and the readable fields. It does not prove that the signature in tags 7 and 9 is genuine. That check needs the signed XML and ZATCA’s own validation, which is done in the SDK or by the platform during clearance and reporting.
Common QR mistakes
ZATCA’s technical guideline lists a few errors that come up again and again. We see the same ones when we review invoice layouts:
- Arabic seller name not in UTF-8. The name scans as question marks or broken characters.
- Length counted in characters, not bytes. An Arabic name of 10 letters is about 20 bytes. If the length byte says 10, every tag after it is read wrong.
- Separators between fields. Commas, spaces or padding between TLV sets break the decode. There must be none.
- Amounts that do not match the invoice. Often the QR is built from the subtotal, or from figures before a document-level discount.
- Printing the wrong QR on B2B invoices. In Phase 2, the cleared QR from ZATCA should be the one on the document.
In SAP Business One, the QR value is normally stored on the A/R invoice (in a user-defined field or the e-document data) and printed through Crystal Reports or the Print Layout Designer as a barcode or image. When the printed code fails, check the stored value first with a TLV decoder. If the stored value is correct, the problem is in the layout, not the integration.
Where this fits in Phase 2
The QR code is the visible end of a longer process: UBL 2.1 XML, hashing, signing with your CSID, and clearance or reporting through ZATCA’s APIs. If any of those steps is wrong, the QR is usually wrong too. Our ZATCA e-invoicing guide covers the full flow, and the Saudi VAT calculator helps when you need to double-check tags 4 and 5 by hand.
If your SAP Business One invoices print a QR code that customers or ZATCA reject, send us a sample and we will tell you which part is failing.
Sources
- ZATCA: E-Invoicing Detailed Technical Guideline, Version 2 (Nov 2022)
- ZATCA: Detailed Guidelines for E-Invoicing, Version 2 (May 2023)
- ZATCA: Electronic Invoice Security Features Implementation Standards (19 May 2023)
- ZATCA Developer Community: Structure of the QR code for electronic tax invoices
- ZATCA: E-Invoicing guidelines page
Related services
Frequently asked questions
How many fields are in a ZATCA QR code?
Up to nine. Tags 1 to 5 hold the seller name, seller VAT number, invoice timestamp, total with VAT and VAT total. Tags 6 to 8 hold the XML invoice hash, the ECDSA signature and the ECDSA public key. Tag 9 is only for simplified invoices and their notes.
Is a QR code required on B2B (standard) tax invoices?
In Phase 1 (generation) it was required only on simplified tax invoices. In Phase 2 (integration), standard tax invoices get their QR code during clearance, when ZATCA's platform stamps the invoice and returns it with the QR code.
What is the maximum length of a ZATCA QR code?
ZATCA's technical guideline says the QR code is encoded in Base64 with up to 700 characters. Each TLV value also has a one-byte length, so a single field cannot be longer than 255 bytes.
Why does my ZATCA QR code show broken Arabic text when scanned?
Usually the seller name was not encoded in UTF-8 before building the TLV, or the length byte was calculated on characters instead of bytes. Arabic letters take two bytes each in UTF-8, so the length must count bytes.
Can a QR scanner app tell me if the invoice is valid?
A normal scanner only shows the Base64 text. A TLV decoder shows the fields so you can compare them with the invoice. Proving the signature is genuine needs the signed XML and ZATCA's validation tools, not the QR code alone.
Ready to get started?
Tell us what you need. You get a clear technical answer, a fixed scope and a price, usually within 24 hours.
