TLV · Encoding
EMV TLV Explained: How Card Data Is Encoded
Almost every piece of data on an EMV chip card, and almost every field the terminal sends to the issuer, is wrapped in the same simple structure: Tag, Length, Value. Once you can read TLV, card responses and ISO 8583 field 55 stop looking like walls of hex.
The three parts
- Tag says what the data is.
9F02is the authorised amount,5Ais the card number. - Length says how many bytes of value follow.
- Value is the data itself.
Here is the authorised amount for a $25.00 purchase:
9F02 06 000000002500
tag len value (n12: 25.00 in minor units)
Reading the tag
EMV uses BER-TLV from ISO/IEC 8825. The first tag byte carries three pieces of information:
| Bits | Meaning |
|---|---|
| b8–b7 | Class: universal, application, context-specific or private. Most EMV tags are application or context-specific. |
| b6 | Primitive (0) or constructed (1). A constructed tag holds more TLV objects inside it. |
| b5–b1 | Tag number. If all five bits are 1 (1F), the tag continues in the next byte. |
That is why 9F02 is two bytes: 9F has its low five bits set, so the parser reads another byte. In each following byte, bit 8 says whether yet another byte follows. 02 has bit 8 clear, so the tag ends there.
Reading the length
- If the first length byte is below
80, it is the length itself:06means 6 bytes. 81means the next byte is the length, for values of 128 to 255 bytes.82means the next two bytes are the length. You will see this with large certificates and records.
A frequent bug is treating 81 as a length of 129. If a parser goes wrong right after a long certificate, check this first.
Templates: TLV inside TLV
Constructed tags group related objects. The ones you meet most often are:
6FFile Control Information, returned by SELECT.70the record template returned by READ RECORD.77Response Message Template Format 2, returned by GET PROCESSING OPTIONS and GENERATE AC.
Here is a shortened GENERATE AC response:
77 14 Format 2 template, 20 bytes
9F27 01 80 Cryptogram Information Data: ARQC
9F36 02 001A Application Transaction Counter: 26
9F26 08 8E31A4F1D5B6C290 Application Cryptogram
The template length, 14 hex or 20 bytes, covers everything inside it: 4 bytes for the CID, 5 for the ATC and 11 for the cryptogram. Checking that the inner objects add up to the outer length is the quickest way to spot truncated data.
Things that trip people up
- Padding. Cards may put
00orFFbytes between objects in a record. Parsers should skip them. - Format 1 responses. Tag
80is primitive. Its value is a fixed sequence of fields with no inner tags, so you split it by position, not by parsing TLV. - Data object lists. PDOL (
9F38) and CDOL1 (8C) look like TLV but contain only tags and lengths, with no values. They tell the terminal what to send. - Proprietary tags. Tags in the
DFand9F5x–9F7xranges are often scheme or kernel specific. Check the scheme specification before assuming a meaning.
Decoding a record byte by byte
Here is a short READ RECORD response, the kind a card returns in every transaction:
70 0E 5A 08 47 61 73 10 00 00 00 43 5F 34 01 01
70: bit 6 is set, so this is a constructed template. The low five bits are not all ones, so the tag is one byte.0E: below80, so the length is 14 bytes. Everything after it belongs to the template.5A: a one-byte primitive tag, the Application PAN.08: 8 bytes of value follow:4761731000000043, a well-known Visa test PAN.5F: the low five bits are all ones, so the tag continues.34has bit 8 clear, so the tag is5F34, the PAN Sequence Number.01 01: one byte of value, sequence number 01.
The inner objects take 10 bytes (2 + 8) and 4 bytes (3 + 1), which add up to the 14 bytes the template declared. The record is complete.
TLV in ISO 8583 field 55
When the terminal goes online, it sends the chip data to the acquirer in field 55 of the ISO 8583 message. Field 55 is a flat list of primitive TLV objects with no template around them: the cryptogram, CID, ATC, TVR, amount, currency, unpredictable number and so on. The field itself has a length prefix defined by the network's message format, which is not part of the TLV data. If your parser fails on the first byte of field 55, check that you removed that prefix.
A checklist for writing your own parser
- Read multi-byte tags by following the
1Frule on the first byte and bit 8 on every following byte, not by looking up a fixed list. - Support the
81and82length forms. Reject80and anything longer than the remaining data. - Check that each value fits inside its parent template before reading it. Never trust a length blindly; a corrupt length is the most common cause of crashes.
- Recurse into constructed tags, and keep the raw bytes of each object so you can display or forward them unchanged.
- Skip
00andFFpadding between objects, but treat anFFfollowed by another byte as the start of a tag such asFF8105. - Keep unknown tags. Proprietary data is often exactly what an issuer or kernel vendor needs to see in a log.
Frequently asked questions
Does the order of tags matter?
In card records and field 55, the order of TLV objects does not change their meaning. Data built from a data object list is different: CDOL1 or PDOL data is a plain concatenation of values in the exact order the list gives, with no tags or lengths.
What is the difference between BER-TLV and SIMPLE-TLV?
SIMPLE-TLV, defined in ISO/IEC 7816-4, always uses a one-byte tag and a length of one byte, or FF followed by two bytes. It has no constructed objects. EMV uses BER-TLV for card data, so a SIMPLE-TLV parser will misread multi-byte tags such as 9F26.
Can the same tag appear twice?
EMV does not expect a card to return the same primitive data object twice in a transaction, and many kernels treat a duplicate as a card data error. If you see duplicates in a log, check whether two templates were merged or a record was read twice.
Try it. Paste any of the examples above into the TLV parser to see each tag named and decoded.