Smart Card ATR (Answer-to-Reset) — Developer Guide

When a smart card is powered on, it sends an Answer-to-Reset (ATR) — a sequence of bytes that tells the reader everything about the card's communication capabilities: which protocol it speaks (T=0 or T=1), what voltage it supports, what clock frequency it expects, and who manufactured it. If you're developing smart card readers, writing card drivers, or debugging card communication failures, understanding the ATR is the first step.

Try it now: Paste any ATR hex string into our ATR Decoder to get an instant byte-by-byte breakdown.

ATR Structure at a Glance

An ATR is a variable-length byte string (2–33 bytes) with this structure:

FieldBytesDescription
TS1Initial character — direct (3B) or inverse (3F) convention
T01Format byte — indicates presence of TA1/TB1/TC1/TD1 + historical byte count
TAi TBi TCi TDi0–15Interface bytes (protocol parameters)
Historical0–15Card-specific data (manufacturer, OS version, serial, etc.)
TCK0–1Check byte (XOR of all bytes from T0 onward; present only if T=1 or multi-protocol)

1. TS — Initial Character

The very first byte of the ATR tells the reader which bit convention the card uses:

ValueConventionDescription
3BDirectMost significant bit first (standard). Used by >95% of cards.
3FInverseLeast significant bit first (rare, some legacy cards).
Quick check: If your ATR starts with 3B, you're reading it correctly. If it starts with 3F, the card uses inverse convention and all subsequent bytes must be interpreted with reversed bit order. Most modern readers handle this transparently.

2. T0 — Format Byte

T0 is the second byte and encodes two things:

T0 = Y1 || K
     \____/  \_/
     bits 7-4  bits 3-0

Y1 (upper nibble): Bit flags indicating which interface bytes follow
  bit 7 = 1 → TA1 present
  bit 6 = 1 → TB1 present
  bit 5 = 1 → TC1 present
  bit 4 = 1 → TD1 present

K (lower nibble): Number of historical bytes (0–15)

Example

If T0 = 95 (binary 10010101):

3. Interface Bytes (TAi, TBi, TCi, TDi)

Interface bytes carry protocol parameters. The first set (TA1/TB1/TC1/TD1) is indicated by T0. Each subsequent TDi byte indicates whether more interface bytes follow for protocol i+1.

TA1 — Fi, Di (Clock and Bit Rate)

TA1 = Fi || Di
      \_/  \_/
   bits 7-4  bits 3-0

Fi: Clock rate integer (lookup table → f(max) in MHz)
Di: Bit rate adjustment (lookup table → D value)
Fif(max) MHzDiD
0Reserved0Reserved
1511
2622
3834
41248
516516
620632
7Reserved812
925920

The effective bit rate is: bit_rate = D × f(clock) / (F × 8), where F is from the Fi table (e.g., F1=372, F2=558, F3=744, F4=1116, F5=1488, F6=1860, F9=512).

TB1 — Vpp Programming Voltage (Deprecated)

TB1 carries programming voltage parameters (Vpp). In modern cards (ISO 7816-3:2006+), TB1 is typically 00 or absent — Vpp is no longer used. If present, it encodes PI1 (programming voltage) and II (maximum programming current).

TB1 is deprecated. Since the 2006 revision of ISO 7816-3, programming voltage pins (Vpp/C4/C6) are no longer used. Most modern ATRs omit TB1 entirely.

TC1 — Extra Guard Time (N)

TC1 specifies the extra guard time N added between consecutive characters. A value of FF means the guard time is reduced to the minimum (11 etu for T=0, 12 etu for T=1). Most cards send TC1=00 (no extra guard time) or FF (reduced guard time).

TD1 — Protocol Type + Next Interface Bytes

TDi = Yi+1 || T
      \_____/  \_/
   bits 7-4    bits 3-0

Yi+1: Bit flags for next interface bytes (same format as T0 upper nibble)
T: Protocol type
  0 = T=0 (byte-oriented, half-duplex)
  1 = T=1 (block-oriented, full-duplex)
  2-13 = Reserved / RFU
  14 = Vendor-specific
  15 = Not applicable

Subsequent Interface Bytes (TAi/TBi/TCi/TDi for i ≥ 2)

ByteProtocolMeaning
TA2T=0Specific mode indication (if present, card is in specific mode)
TA2T=1IFSC (Information Field Size for the Card) — max 254
TB2T=1BWI (Block Waiting Time Integer) || CWI (Character Waiting Time Integer)
TC2T=0WWT (Waiting Time Integer) for T=0
TD2AnyProtocol for next group + Yi+3 flags

4. Historical Bytes

The K historical bytes (K from T0) contain card-specific information. There is no standard format, but common conventions exist:

ISO 7816-4 Category Indicator

If the first historical byte is:

ValueCategoryRemaining Bytes
80Compact TLVOne status byte + compact TLV data
00Not compact TLVRemaining bytes are card issuer proprietary
OtherNot compact TLVCard issuer proprietary

Common Compact TLV Tags

TagMeaningLength
0x31Country code (ISO 3166-1 numeric)1–2
0x32Issuer identification numberVariable
0x33Card service data1
0x34Initial access dataVariable
0x35Card issuer dataVariable
0x36Pre-issuing dataVariable
0x50Application identifier (AID)Variable
0x7FStatus indicator (with sub-tags)Variable

Java Card Historical Bytes

Java Card applets typically include the Java Card AID (e.g., A000000062) or a GlobalPlatform AID (e.g., A0000001510000) in the historical bytes.

5. TCK — Check Byte

TCK is the XOR of all ATR bytes from T0 to the last byte before TCK:

TCK = T0 XOR TA1 XOR TB1 XOR ... XOR TDi XOR Historical[0] XOR ... XOR Historical[K-1]

TCK is present only when the ATR indicates T=1 or multiple protocols. If the card uses only T=0 and no TD1 byte is present, TCK is absent.

Validation: If you XOR all bytes from T0 through TCK (inclusive), the result should be 00. If it's not, the ATR is corrupted.

6. Real-World ATR Examples

Example 1: Basic T=0 SIM Card

ATR: 3B 9A 00 92 01 92 44 53 49 4D 32 34 82

Byte  Value  Description
TS    3B     Direct convention
T0    9A     Y1=1001 (TA1+TD1), K=10 historical bytes
TA1   00     Fi=0/Di=0 → default (372/1 = 9600 bps at 3.5795 MHz)
TD1   92     Y2=1001 (TA2+TD2), T=2... wait

Let me use a cleaner example:

ATR: 3B 16 94 10 10 92 00 00

TS    3B     Direct convention
T0    16     Y1=0001 (TA1 present), K=6 historical bytes
TA1   94     Fi=9/Di=4 → F=512, D=8 → 25 MHz / high speed
Hist  10 10 92 00 00 → 5 historical bytes (manufacturer data)

Example 2: Java Card with T=0 + T=1

ATR: 3B 7F 96 00 00 80 31 80 65 B0 83 41 3D F6

TS    3B     Direct convention
T0    7F     Y1=0111 (TA1+TB1+TC1), K=15 historical bytes
TA1   96     Fi=9/Di=6 → F=512, D=32 → high-speed
TB1   00     No Vpp
TC1   00     No extra guard time
Hist  00 80 31 80 65 B0 83 41 3D F6
      → 80 = compact TLV category
      → 31 80 → Country code tag, no data
      → 65 B0 → Card service data
      → 83 41 3D → Status info
TCK   F6     Check byte (XOR of T0..last historical = F6)

Example 3: NXP JCOP Card (T=1)

ATR: 3B F5 96 00 00 80 31 FE 45 4A 43 4F 50 33 02

TS    3B     Direct convention
T0    F5     Y1=1111 (TA1+TB1+TC1+TD1), K=5 historical bytes
TA1   96     Fi=9/Di=6
TB1   00     No Vpp
TC1   00     No extra guard time
TD1   80     Y2=1000 (TD2 present), T=0 (first protocol is T=0)
TD2   31     Y3=0011 (TA3+TB3), T=1 (second protocol is T=1)
TA3   FE     IFSC = 254 (max T=1 information field size)
TB3   45     BWI=4, CWI=5 → BWT=4.6s, CWT=8.1ms
Hist  4A 43 4F 50 33 → "JCOP3" (Java Card Open Platform 3)
TCK   02     Check byte

7. Protocol Selection

When a card supports multiple protocols (e.g., T=0 and T=1 via TD1/TD2), the reader must decide which to use:

  1. Default protocol: The first protocol indicated by TD1. If TD1 is absent, the default is T=0.
  2. Negotiable mode: If TA2 is absent, the card is in negotiable mode. The reader can request a protocol change using PPS (Protocol and Parameter Selection).
  3. Specific mode: If TA2 is present, the card is in specific mode and will only use the protocol indicated by TA2.

PPS (Protocol and Parameter Selection)

Reader → Card:  PPSS || PPS0 || [PPS1] || [PPS2] || [PPS3] || PPS_END
Card  → Reader: PPSS || PPS0 || [PPS1] || [PPS2] || [PPS3] || PPS_END

PPSS   = 0xFF (PPS start byte)
PPS0   = format byte (like T0, indicates which PPS1/2/3 follow + protocol T)
PPS1   = TA1 value (Fi/Di to negotiate)
PPS2   = specific parameters
PPS3   = specific parameters
PPS_END = 0xFF (not always required)

If the card returns the same PPS → accepted. If error → rejected.

8. Common ATR Patterns

ATR PrefixCard TypeNotes
3B 00Basic T=0Minimal ATR, no interface bytes, no historical bytes
3B 9xStandard T=0T=0 with interface bytes, common for SIM/USIM
3B 7FMulti-protocolT=0 + T=1, Java Card / GlobalPlatform
3B FxT=0 + T=1Full interface byte set, often JCOP cards
3B 90T=0 onlyTA1 present, no TB1/TC1/TD1
3B A5ExtendedTA1+TC1 present, K=5

Famous Historical Byte Patterns

Historical BytesASCIICard
4A 43 4F 50 33JCOP3NXP JCOP 3 Java Card
44 53 49 4DDSIMGSM SIM card
55 53 49 4DUSIM3G/4G USIM card
49 53 44ISDGlobalPlatform Issuer Security Domain
56 49 53 41VISAVisa EMV card
4D 43MCMastercard EMV card

9. Python ATR Parser

def parse_atr(hex_str: str) -> dict:
    """Parse an ATR hex string into its components."""
    atr = bytes.fromhex(hex_str.replace(" ", ""))
    idx = 0
    result = {}

    # TS
    result["TS"] = atr[idx]
    result["convention"] = "direct" if atr[idx] == 0x3B else "inverse"
    idx += 1

    # T0
    t0 = atr[idx]
    result["T0"] = t0
    y1 = (t0 >> 4) & 0xF
    k = t0 & 0xF
    result["K"] = k
    idx += 1

    # Interface bytes group 1
    iface = {}
    if y1 & 0x8: iface["TA1"] = atr[idx]; idx += 1
    if y1 & 0x4: iface["TB1"] = atr[idx]; idx += 1
    if y1 & 0x2: iface["TC1"] = atr[idx]; idx += 1
    if y1 & 0x1:
        iface["TD1"] = atr[idx]
        result["protocol_TD1"] = atr[idx] & 0xF
        idx += 1
    result["interface_bytes"] = iface

    # Subsequent interface byte groups (TD2, TA2, etc.)
    group = 1
    while True:
        td_key = f"TD{group}"
        if td_key not in iface:
            break
        yi = (iface[td_key] >> 4) & 0xF
        result[f"protocol_T{group+1}"] = iface[td_key] & 0xF
        group += 1
        new_iface = {}
        if yi & 0x8: new_iface[f"TA{group}"] = atr[idx]; idx += 1
        if yi & 0x4: new_iface[f"TB{group}"] = atr[idx]; idx += 1
        if yi & 0x2: new_iface[f"TC{group}"] = atr[idx]; idx += 1
        if yi & 0x1:
            new_iface[f"TD{group}"] = atr[idx]; idx += 1
        iface.update(new_iface)
        if not (yi & 0x1):
            break

    # Historical bytes
    hist_start = idx
    result["historical"] = list(atr[idx:idx+k])
    idx += k

    # TCK (check byte)
    if idx < len(atr):
        result["TCK"] = atr[idx]
        # Verify
        xor = 0
        for i in range(1, len(atr)):
            xor ^= atr[i]
        result["TCK_valid"] = (xor == 0)

    return result

# Example usage
atr_hex = "3BF59600008031FE454A434F503302"
result = parse_atr(atr_hex)
for k, v in result.items():
    print(f"{k}: {v}")

10. JavaScript ATR Parser (Browser)

function parseATR(hexStr) {
    const atr = hexStr.replace(/\s/g, '');
    const bytes = [];
    for (let i = 0; i < atr.length; i += 2) {
        bytes.push(parseInt(atr.substr(i, 2), 16));
    }

    let idx = 0;
    const result = {};

    // TS
    result.TS = bytes[idx];
    result.convention = bytes[idx] === 0x3B ? 'direct' : 'inverse';
    idx++;

    // T0
    const t0 = bytes[idx];
    result.T0 = t0;
    let y = (t0 >> 4) & 0xF;
    const k = t0 & 0xF;
    result.K = k;
    idx++;

    // Interface bytes
    result.interfaceBytes = {};
    let group = 1;

    while (y > 0) {
        if (y & 0x8) result.interfaceBytes[`TA${group}`] = bytes[idx++];
        if (y & 0x4) result.interfaceBytes[`TB${group}`] = bytes[idx++];
        if (y & 0x2) result.interfaceBytes[`TC${group}`] = bytes[idx++];
        if (y & 0x1) {
            result.interfaceBytes[`TD${group}`] = bytes[idx];
            y = (bytes[idx] >> 4) & 0xF;
            result[`protocol_T${group}`] = bytes[idx] & 0xF;
            idx++;
            group++;
        } else {
            break;
        }
    }

    // Historical bytes
    result.historicalBytes = bytes.slice(idx, idx + k);
    idx += k;

    // TCK
    if (idx < bytes.length) {
        result.TCK = bytes[idx];
        let xor = 0;
        for (let i = 1; i < bytes.length; i++) xor ^= bytes[i];
        result.TCK_valid = xor === 0;
    }

    return result;
}

11. Common Debugging Issues

ATR too short: If you only get 2 bytes (e.g., 3B 00), the card may not be fully powered or the reader is timing out. Check VCC and clock signal.
ATR too long (>33 bytes): Per ISO 7816-3, the maximum ATR length is 33 bytes (including TS and TCK). If you read more, you're likely reading past the ATR into the card's first response.
TCK validation failure: If XOR of T0..TCK ≠ 0, the ATR was corrupted during transmission. This usually indicates electrical issues (bad contacts, noise, incorrect VCC).
Unexpected protocol: If your application expects T=1 but the card only supports T=0 (no TD1 or TD1 indicates T=0), you must either use T=0 or send a PPS request to negotiate T=1. Not all cards support PPS.

12. Summary

ATR parsing checklist: 1. Read TS → determine convention (3B = direct, 3F = inverse) 2. Read T0 → get interface byte flags (Y1) and historical byte count (K) 3. Read interface bytes indicated by Y1 (TA1, TB1, TC1, TD1) 4. If TD1 present, continue reading interface bytes for next protocol group 5. Read K historical bytes 6. If T=1 or multi-protocol, verify TCK 7. Identify protocol: default is T=0 unless TD1 specifies otherwise

Use our ATR Decoder for instant parsing, or the APDU Builder to construct your first command after parsing the ATR. For a closer look at card communication, see our ISO 7816 Protocol Reference and PC/SC Programming Guide.