All Tools
Tools/EMV TLV Decoder
🔓
EMV & ChipAvailable
EMV TLV Decoder
Decode TLV-encoded hex bytes (e.g. from DE55 / tag 77 response) into a structured, annotated list of EMV tag/length/value records with descriptions.
Follows EMV Book 34.4·verified Oct 2026· double-checked Oct 2026— Annex B BER-TLV (lengths 81/82/83, 00 padding; FF skips reported); values per Annex A1, Book 4 and ISO 4217 / 3166-1; 10,000 trees match an independent decoder and proxmark3
Try it as a puzzle: route a chip payment to the card’s bank →
Examples:
</> Code Implementation
# BER-TLV Parser — decode EMV tag-length-value structures
# No external dependencies required
def parse_tlv(hex_str: str) -> list:
data = bytes.fromhex(hex_str.replace(" ", ""))
results, i = [], 0
while i < len(data):
# Padding: 00 (EMV Book 3 Annex B) or FF (ISO/IEC 7816-4), but not the FF of a
# Kernel 2 FF81xx tag
if data[i] == 0x00 or (data[i] == 0xFF and data[i + 1:i + 2] != b"\x81"):
i += 1; continue
# Tag: more bytes follow while b8 is set (first byte: if b5-b1 = 11111)
start = i
i += 1
if (data[start] & 0x1F) == 0x1F:
while data[i] & 0x80: i += 1
i += 1
tag_hex = data[start:i].hex().upper()
# Length
l = data[i]; i += 1
if l & 0x80: # long form
n = l & 0x7F
length = int.from_bytes(data[i:i+n], "big"); i += n
else:
length = l
value = data[i:i+length]; i += length
results.append({"tag": tag_hex, "length": length, "value": value.hex().upper()})
return results
# Example
tlv = "9F02060000000025009A03260101"
for t in parse_tlv(tlv):
print(f"Tag: {t['tag']} Len: {t['length']:02d} Value: {t['value']}")
# Tag: 9F02 Len: 06 Value: 000000002500
# Tag: 9A Len: 03 Value: 260101
Something wrong or missing? Report a problem— we check reports against the specs and fix them.