If you’ve ever looked at an international tracking number like LX123456789CN or EE987654321US and wondered why every postal service in the world produces numbers in the same shape, the answer is the UPU S10 standard.

This is the format used by every member country of the Universal Postal Union for cross-border letters and parcels. Once you understand it, you can validate tracking numbers, identify the originating country, and even spot typos before sending an API request.

This guide breaks down the format down to the character, including the often-skipped check-digit math.

What Is UPU S10?

The Universal Postal Union (UPU) is the United Nations agency that coordinates international mail. S10 is one of its technical standards, defining a 13-character identifier used on items sent across borders through the postal system.

The format is fixed:

Format: AA NNNNNNNN N AA
        │  │        │ │
        │  │        │ └─ 2-letter ISO country code of the origin
        │  │        └─── Check digit (1 digit, computed from the serial)
        │  └──────────── 8-digit serial number
        └─────────────── 2-letter service indicator

Total length: 13 characters. 2 letters + 9 digits + 2 letters. That phrase shows up in dozens of search queries because it’s the single most useful way to remember the structure.

Breaking Down the 13 Characters

Characters 1–2 — Service Indicator (2 letters)

The first two letters tell you what kind of postal service the item used. The first letter is the service category, the second letter is a specific service variant within that category.

First letterService categoryExamples
EExpress Mail Service (EMS)EE, EA, EM (priority international)
RRegistered MailRR, RA, RX (signed-for letters)
CInsured ParcelCC, CP, CX (tracked parcels)
LLetter Post (signed)LL, LX, LZ (small letter packets)
VInsured LetterVV, VR (declared-value letters)
UUnregistered untrackedUA, UB (rare)

Examples in the wild:

  • EE... — EMS Express
  • RR... — Registered Mail
  • LX... — Tracked letter / small packet
  • CP... — International Parcel

Characters 3–10 — 8-Digit Serial Number

Eight numeric digits, assigned sequentially by the originating postal operator. Nothing special about them on their own — but the next character depends on them.

Character 11 — Check Digit (1 digit)

This is the only character that matters for validation, and it’s the one most engineers miss. The check digit is computed from the 8 serial digits using a fixed weighted-sum formula.

Algorithm:

  1. Multiply each of the 8 serial digits by a fixed weight: [8, 6, 4, 2, 3, 5, 9, 7]
  2. Sum the products
  3. Compute remainder = sum mod 11
  4. The check digit is:
    • 0 if remainder == 1
    • 5 if remainder == 0
    • otherwise 11 - remainder

JavaScript:

function s10CheckDigit(serial8) {
  const weights = [8, 6, 4, 2, 3, 5, 9, 7];
  const sum = serial8
    .split('')
    .reduce((acc, ch, i) => acc + Number(ch) * weights[i], 0);
  const r = sum % 11;
  if (r === 1) return 0;
  if (r === 0) return 5;
  return 11 - r;
}

function isValidS10(trackingNumber) {
  if (!/^[A-Z]{2}\d{9}[A-Z]{2}$/.test(trackingNumber)) return false;
  const serial = trackingNumber.slice(2, 10);
  const claimed = Number(trackingNumber[10]);
  return s10CheckDigit(serial) === claimed;
}

This catches the most common error — a single mistyped digit — without making any API call.

Characters 12–13 — Country Code (2 letters)

The final two characters are the ISO 3166-1 alpha-2 country code of the postal service that originated the item — not the destination.

CodePostal operator
USUSPS — United States Postal Service
GBRoyal Mail — United Kingdom
CNChina Post
JPJapan Post
KRKorea Post
DEDeutsche Post
FRLa Poste
CACanada Post
AUAustralia Post
SGSingapore Post
INIndia Post
NLPostNL

So LX123456787CN is a tracked letter shipped from China, regardless of where it’s headed.

Examples by Major Postal Carrier

Tracking numberServiceOrigin
EE123456785USUSPS Priority Mail International / EMSUnited States
RR123456789GBRoyal Mail Tracked & SignedUnited Kingdom
LX123456784CNChina Post tracked small packetChina
RR987654321JPJapan Post Registered MailJapan
EA123456789KRKorea Post EMSSouth Korea
RA123456789DEDeutsche Post Einschreiben (Registered)Germany
CP111222333CACanada Post International ParcelCanada
EM123456789AUAustralia Post Express Courier InternationalAustralia

(Check digits in this table are illustrative — your real numbers will compute differently.)

What S10 Does NOT Cover

S10 is for international postal items only. Domestic-only tracking numbers and private courier numbers use completely different formats:

  • USPS domestic — 20–22 digits (9400 1xxx..., 9405 5xxx...)
  • UPS1Z + 16 alphanumeric (1Z999AA10123456784)
  • FedEx — 12, 15, or 20 digits
  • DHL Express — 10 digits, no letters
  • CJ Logistics, Yamato, Sagawa — purely numeric, no S10 prefix

If a tracking number you’re handed doesn’t match ^[A-Z]{2}\d{9}[A-Z]{2}$, it isn’t S10. It might still be a perfectly valid tracking number — just from a different format family.

For a fuller breakdown of those domestic formats, see Understanding Tracking Number Formats by Carrier.

Common Misconceptions

  • “The country code is the destination.” No — it’s the origin. A ...US number was sent from the United States, even if it ends up in Germany.
  • “The check digit is just a random digit.” It isn’t — it’s deterministic. If your input fails the check, the number is wrong.
  • “All international tracking is S10.” No. Many private couriers (DHL Express, FedEx, UPS) carry international shipments under their own non-S10 numbering.
  • “Lowercase is fine.” S10 numbers are always uppercase. Normalize the input before validating.

Validating S10 in Practice

Combine the regex shape check with the check-digit math. Here’s a complete validator that handles whitespace, case, and the math in one function:

function validateS10(input) {
  const cleaned = input.replace(/[\s\-]/g, '').toUpperCase();
  if (!/^[A-Z]{2}\d{9}[A-Z]{2}$/.test(cleaned)) {
    return { valid: false, reason: 'wrong_shape' };
  }
  const serial = cleaned.slice(2, 10);
  const claimed = Number(cleaned[10]);
  const weights = [8, 6, 4, 2, 3, 5, 9, 7];
  const sum = serial.split('').reduce((a, c, i) => a + Number(c) * weights[i], 0);
  const r = sum % 11;
  const expected = r === 1 ? 0 : r === 0 ? 5 : 11 - r;
  if (expected !== claimed) {
    return { valid: false, reason: 'check_digit_mismatch', expected };
  }
  return {
    valid: true,
    service: cleaned.slice(0, 2),
    serial,
    countryCode: cleaned.slice(11, 13),
  };
}

This is good enough for client-side validation, customer-input forms, and pre-API filtering. It catches both “user typed it wrong” and “this isn’t actually a tracking number.”

Auto-Detection with WhereParcel

Even with perfect S10 validation, you still don’t know which postal operator to query — only the country of origin. You’d then need to map US → USPS, GB → Royal Mail, etc., and decide whether the destination’s postal service is also worth querying for inbound visibility.

WhereParcel handles this automatically. Pass carrier: "auto" and the API identifies the right operator, queries it, and returns a unified JSON status.

curl -X POST https://api.whereparcel.com/v2/track \
  -H "Authorization: Bearer YOUR_API_KEY:YOUR_SECRET_KEY" \
  -d '{"trackingItems": [{"carrier": "auto", "trackingNumber": "EE123456785US"}]}'
{
  "success": true,
  "data": {
    "carrier": "us.usps",
    "carrierName": "USPS",
    "trackingNumber": "EE123456785US",
    "status": "in_transit"
  }
}

You write the validator once, the API takes over for the actual lookup.

Summary

The UPU S10 format is 2 letters + 9 digits + 2 letters:

  • 2-letter service indicator (E/R/C/L/V/U + variant)
  • 8-digit serial
  • 1 check digit (deterministic, weighted-sum formula)
  • 2-letter ISO country code (origin, not destination)

That’s it. Once you have the regex and the check-digit math, you can validate any S10 tracking number in any language in about 20 lines of code.

For the actual cross-carrier lookup, see the WhereParcel docs — auto-detection across 64+ live carriers is built in (request additions anytime).

Or paste any number into our free Tracking Number Validator — it auto-detects USPS, UPS, FedEx, DHL, OnTrac, Amazon Logistics, UPU S10, and more from the format alone (no signup needed).


Related guides: