TRC20 Address Format Explained and How to Validate It
Learn the TRC20 address format: how a 34-character TRON address starting with T is built, what its Base58Check checksum does and how to validate one in code.

The TRC20 address format describes the addresses used to send and receive USDT and TRX on the TRON network. A TRON address always starts with a capital "T", is 34 characters long and carries a checksum that catches typos. This article explains how a TRC20 address is built, how to validate one by eye and in code, and what validation can and can't tell you.
Is a TRC20 address the same as a TRON address?
Yes. "TRC20" is the name of TRON's token standard, not an address type. USDT (TRC20) and TRX are both sent to the same TRON address. When people say "TRC20 address", they mean a TRON address.
Why does this matter? The same USDT moves on several networks with different address formats. ERC20 and BEP20 addresses start with 0x, while TRON addresses start with T. The networks are compared in what is USDT: TRC20 vs ERC20 vs BEP20.
Anatomy of a TRON address
A TRON address is a 21-byte value derived from a public key. The first byte is always 0x41, which marks it as a TRON mainnet address. The other 20 bytes come from a hash of the public key.
Those 21 bytes can be shown in two ways:
| Format | Looks like | Where you see it |
|---|---|---|
| Base58Check | 34 characters starting with T |
Wallets, exchanges, payment pages |
| Hex | 42 hex characters starting with 41 |
Some developer tools and raw data |
What users see and copy is the Base58Check form. The 0x41 prefix always encodes to the letter "T", which is why every valid TRON address starts with it.
The Base58 alphabet
Base58 leaves out characters that are easy to confuse. These are not in the alphabet:
0(zero)O(capital o)I(capital i)l(lowercase L)
If an address contains any of them, it's invalid. That rule catches errors early when an address is typed by hand or read from an image.
The checksum
The "Check" in Base58Check is a 4-byte checksum appended to the address. It's the first 4 bytes of a double SHA-256 hash of the 21-byte payload. Change one character and the checksum almost certainly fails, so wallets reject the address.
In short, a valid TRC20 address:
- starts with
T, - is exactly 34 characters,
- uses only Base58 characters,
- decodes to a payload starting with
0x41, - has a correct checksum.
Validating a TRC20 address in code
If customers or staff type TRON addresses into your forms, validate them before saving. This Python function applies all five rules with no extra dependencies:
import hashlib
ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
def is_tron_address(addr: str) -> bool:
if len(addr) != 34 or not addr.startswith("T"):
return False
n = 0
for ch in addr:
i = ALPHABET.find(ch)
if i < 0:
return False # invalid character such as 0, O, I or l
n = n * 58 + i
try:
raw = n.to_bytes(25, "big")
except OverflowError:
return False
payload, checksum = raw[:21], raw[21:]
digest = hashlib.sha256(hashlib.sha256(payload).digest()).digest()
return payload[0] == 0x41 and digest[:4] == checksum
Where should you call it? The best place is the moment an address enters your system: when a form is submitted, when a staff member updates a payout address, or when a customer gives you an address for a refund. Rejecting a bad address then is far cheaper than discovering it when a transfer is attempted. Show a clear message too: "This isn't a TRON (TRC20) address. Please check your 34-character address starting with T." A concrete explanation like that lets the customer fix the problem on their own, where a generic "invalid input" doesn't.
One more caution: trim leading and trailing whitespace when saving, but never touch the characters inside the address. "Fixes" such as changing letter case break a valid address.
Validating with the MercanPay API
If you'd rather not roll your own, use the address lookup in the MercanPay API. GET /v1/chain/addresses/{address} returns valid: false for an invalid address. For a valid one it also tells you whether the address is activated and shows its balances. It works with a read-scoped key.
import os
from mercanpay import MercanPay
zp = MercanPay("https://mercanpay.com", os.environ["MERCANPAY_API_KEY"])
info = zp.address_info("T...")
if not info["valid"]:
print("Not a TRON address")
else:
print("Activated:", info["activated"])
In the PHP library, the same call is $zp->addressInfo('T...'). Other endpoints are in the documentation.
What validation does and doesn't prove
This part matters. Format validation only tells you the address is structurally a valid TRON address. It does not prove:
- That it belongs to the right person. A valid but wrong address is still valid.
- That it wasn't swapped. Clipboard malware and address poisoning produce perfectly valid fake addresses. See address poisoning attacks.
- That the recipient can accept USDT there. An exchange deposit address, for example, may belong to a different network.
So the checksum is a safety net against typos, not a replacement for care. Comparing the start, middle and end of an address is still necessary.
Address format when receiving payments
When you get paid through MercanPay, you never type the customer-facing address. Each invoice is assigned a TRON address automatically and the payment page shows it as text and as a QR code, which removes most copy-paste mistakes. The benefits of QR codes are covered in QR code crypto payments.
Where customers actually slip up is the network choice. What happens when someone sends from another network is explained in crypto sent to the wrong network.
Address format when withdrawing
When you withdraw your balance, you enter the address yourself. These habits help:
- Use saved addresses. Save and label them once in the panel instead of pasting each time.
- Send a small amount first. The minimum withdrawal is $10 worth.
- Copy from the source. Take the address from your exchange or wallet's deposit screen, not from old transaction history.
API withdrawals can only go to saved addresses marked as trusted. The reasoning is in crypto merchant account security.
FAQ
My TRON address starts with a lowercase letter. Is that normal?
No. Every TRON mainnet address in Base58Check form starts with a capital "T". Anything else belongs to another network or is wrong.
Is a TRC20 address case-sensitive?
Yes. Upper- and lowercase letters are different values in Base58. Changing the case of a single letter invalidates the address or breaks its checksum.
I saw a long address starting with 41. What is it?
That's the hex form of the same address. Always give users and wallets the Base58Check form that starts with T.
I sent to a valid but wrong address. Can I get it back?
A confirmed blockchain transaction can't be reversed. If the address belongs to someone else, recovery depends entirely on their goodwill, which is why checking before you send is essential.
Get started with MercanPay
Accept USDT and TRX with an automatically assigned TRON address, a QR code and clear network warnings on every invoice. Apply as a merchant.


