Guide · Node.js · SDK · REST API

Container Code Validation in Node.js — ISO 6346 Explained

Every shipping container crossing the ocean carries a unique 11-character code governed by ISO 6346. Here's how the standard works, what each part of the code means, how the mod-11 check digit catches transposition errors, and how to validate container codes in your Node.js application.

1. What is ISO 6346?

ISO 6346 is an international standard that defines the coding, identification, and marking of shipping containers used in intermodal freight transport. Published by the International Organization for Standardization, it assigns each container a globally unique 11-character code consisting of letters and digits.

The standard is maintained by the Bureau International des Containers (BIC), which operates the global registry of owner codes. Every container manufacturer, leasing company, and shipping line must register its owner code with BIC before putting containers into service.

In logistics software, container codes appear in bills of lading, customs declarations, terminal operating systems, and vessel manifests. A single transposition error can route a container to the wrong yard, delay customs clearance, or generate phantom inventory.


2. Anatomy of a container code

An ISO 6346 container code has exactly 11 characters, split into four parts:

CSQU3054383

Owner Code

CSQ

3 letters — BIC-registered

Category

U

1 letter — equipment type

Serial Number

305438

6 digits — unique per owner

Check Digit

3

1 digit — mod-11 validation

ℹ️The owner code is always three uppercase letters (A-Z). The category identifier is a single letter. Together with the six-digit serial number and one-digit check digit, this forms the complete 11-character container code.

3. The mod-11 check digit algorithm

ISO 6346 uses a weighted mod-11 algorithm. Each of the first 10 characters is assigned a numeric value, multiplied by a power-of-2 weight, and the sum modulo 11 produces the check digit. If the result is 10, it is mapped to 0.

Let's walk through CSQU3054383:

Step 1 — Convert letters to numbers

Letters are mapped: A=10, B=12, C=13, D=14, ... skipping multiples of 11 (11, 22, 33). So A=10, B=12, C=13, ..., K=21, L=23, ..., and so on. Digits 0-9 keep their face value.

CharacterCSQU3054383
Value13302832305438?

Step 2 — Multiply by powers of 2

Weight (2^i)1248163264128256512
Product13601122564803205127684096?

Step 3 — Sum and apply mod 11

13 + 60 + 112 + 256 + 48 + 0 + 320 + 512 + 768 + 4096 = 6185

6185 % 11 = 3

Check digit is 3 — matches the 11th character of CSQU3054383

// containerCheckDigit.js — ISO 6346 mod-11 check digit
function validateContainerCode(code) {
  code = code.toUpperCase().replace(/[\s-]/g, '');
  if (!/^[A-Z]{3}[UJZR]\d{7}$/.test(code)) return false;

  // Letter-to-number mapping: A=10, B=12, C=13, ... (skip multiples of 11)
  function charValue(ch) {
    if (ch >= '0' && ch <= '9') return parseInt(ch, 10);
    const n = ch.charCodeAt(0) - 'A'.charCodeAt(0);
    // value = 10 + n + floor((n + 8) / 10) — skips 11, 22, 33
    return 10 + n + Math.floor((10 + n) / 11);
  }

  let sum = 0;
  for (let i = 0; i < 10; i++) {
    sum += charValue(code[i]) * Math.pow(2, i);
  }

  const checkDigit = sum % 11 % 10; // if mod-11 gives 10, map to 0
  return checkDigit === parseInt(code[10], 10);
}

console.log(validateContainerCode('CSQU3054383')); // true  ✓
console.log(validateContainerCode('CSQU3054384')); // false ✗ wrong check digit
console.log(validateContainerCode('MAEU1234567')); // checks dynamically

4. Category codes — U, J, Z, R

The fourth character of a container code identifies the type of equipment. ISO 6346 defines four category identifiers:

CodeCategoryDescription
UFreight containerStandard dry, high-cube, open-top, flat-rack, and other general-purpose containers
JDetachable equipmentDetachable freight container-related equipment such as generator sets
ZTrailer / ChassisTrailers and chassis used in intermodal transport
RReefer containerRefrigerated containers with integrated cooling units
⚠️The vast majority of containers in circulation use category U (freight container). Category R for reefers is less common in ISO 6346 markings because many reefer containers are still marked with U and identified as reefers through their ISO size-type code instead.

5. Why container code validation matters

Customs and regulatory compliance

Customs authorities worldwide require valid container codes on all import/export declarations. An invalid code will cause the declaration to be rejected, delaying cargo clearance and potentially incurring demurrage charges.

Terminal operating systems

Port terminals use container codes to track containers through gate-in, yard placement, vessel loading, and gate-out. A mistyped code creates phantom entries in the yard plan — operators search for a container that appears to exist but cannot be physically located.

BIC registry and owner identification

The three-letter owner code is registered with BIC (Bureau International des Containers). Validating the check digit confirms the code was transcribed correctly, but does not confirm the owner code is registered. For owner verification, a separate BIC registry lookup is needed.

Supply chain visibility

Freight forwarders, 3PLs, and BCOs track containers across multiple carriers and modes. A single digit error in a container code breaks the tracking chain and makes the shipment invisible until someone manually reconciles the records.


6. The production-ready solution

The IsValid Container Code API validates the format, computes the ISO 6346 mod-11 check digit, and returns the parsed components — owner code, category, serial number, and check digit — in a single call.

ISO 6346
Standard
full compliance
<15ms
Response time
pure algorithmic check
100/day
Free tier
no credit card

Full parameter reference and response schema: Container Code Validation API docs →


7. Node.js code example

import { createClient } from '@isvalid-dev/sdk';

const iv = createClient({ apiKey: process.env.ISVALID_API_KEY });

// ── Example usage ────────────────────────────────────────────────────────────

const result = await iv.containerCode('CSQU3054383');

if (!result.valid) {
  console.log('Invalid container code');
} else {
  console.log('Owner code:', result.ownerCode);       // → 'CSQ'
  console.log('Category:', result.categoryName);       // → 'Freight container'
  console.log('Serial:', result.serialNumber);         // → '305438'
  console.log('Check digit:', result.checkDigit);      // → '3'
}

In a cargo manifest processing pipeline:

// Validate container codes in a vessel manifest
async function processManifest(containers) {
  const results = [];

  for (const entry of containers) {
    if (!entry.containerCode) {
      results.push({ ...entry, status: 'missing' });
      continue;
    }

    const check = await validateContainerCode(entry.containerCode);

    if (!check.valid) {
      results.push({ ...entry, status: 'invalid' });
      continue;
    }

    results.push({
      ...entry,
      containerCode: entry.containerCode.toUpperCase().replace(/[\s-]/g, ''),
      ownerCode: check.ownerCode,
      category: check.categoryName,
      serialNumber: check.serialNumber,
      status: 'valid',
    });
  }

  return results;
}
Always normalise container codes to uppercase before validation. ISO 6346 codes are case-insensitive by convention, but the standard defines only uppercase letters. Strip spaces and hyphens — some systems format codes as CSQU 305438-3.

8. cURL example

Validate a standard freight container:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/container-code?value=CSQU3054383"

Validate a container with an invalid check digit:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/container-code?value=CSQU3054380"

Validate a reefer container:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/container-code?value=TRIU4567890"

9. Understanding the response

Valid container code:

{
  "valid": true,
  "ownerCode": "CSQ",
  "categoryCode": "U",
  "categoryName": "Freight container",
  "serialNumber": "305438",
  "checkDigit": "3"
}

Invalid container code:

{
  "valid": false
}
FieldTypeDescription
validbooleanFormat correct, category valid, mod-11 check digit passes
ownerCodestring3-letter BIC owner code (e.g. "CSQ", "MAE", "MSC")
categoryCodestringSingle letter: U, J, Z, or R
categoryNamestringHuman-readable category name (e.g. "Freight container")
serialNumberstring6-digit serial number assigned by the owner
checkDigitstringSingle check digit (0-9) computed via mod-11

10. Edge cases — tanks, reefers, and more

Tank containers

ISO tank containers (for liquids, gases, and powders) use the same coding scheme with category U. They are distinguished from dry containers by the ISO size-type code painted on the container (e.g. 22T0 for a standard tank), not by the owner/category code.

Reefer containers and the R category

While ISO 6346 defines R for reefer containers, in practice most reefer containers carry a U category code. The reefer nature is identified by the size-type code (e.g. 45R1). Your validation should accept both U and R for reefer containers.

Check digit 10 → 0 mapping

When the mod-11 computation yields 10, the check digit is mapped to 0. This is a known edge case — approximately 1 in 11 containers will have this mapping. If your validation logic does not handle this, it will incorrectly reject valid containers.

// The critical line in the check digit calculation:
const checkDigit = sum % 11 % 10; // double-mod handles 10 → 0

Lowercase and formatting variants

Container codes may arrive from OCR systems, manual data entry, or EDI messages in mixed case or with embedded spaces/hyphens. Always normalise to uppercase and strip non-alphanumeric characters before validation. The code csqu 305438-3 is the same container as CSQU3054383.


Summary

Do not skip the mod-11 check digit — transposition errors are common in manual entry
Do not assume all reefers use category R — most use U with a reefer size-type code
Normalise to uppercase and strip spaces/hyphens before validation
Handle the check digit 10 → 0 mapping (double-mod trick)
Store the parsed owner code for BIC registry lookups if needed
Validate at the point of data entry — customs and terminal systems will reject bad codes

See also

Validate container codes instantly

Free tier includes 100 API calls per day. No credit card required. Full ISO 6346 validation with parsed owner code, category, and check digit.