jkeen/tracking_number_data

Shared data for cross platform tracking number detection

143

stars

237

commits

JavaScript

primary language

Sep 2, 2026

updated

trackingnumber.fyi/Browse cluster: Svelte UI components and design systems

README

Tests Release Semantic versioning Semantic release

Tracking Number Data

This repository contains json files that programmatically describe how to detect, validate, and decode tracking numbers. The collection started in the tracking_number ruby gem in 2010, and split out here in 2017 so that any language could use it.

trackingnumber.fyi consumes the latest release of this data. Paste a number in and it will tell you which carrier it belongs to and illustrate, digit by digit, what each part of that number means.

Libraries built on this data

Written one for a language that isn't listed? Open a PR to get it added to this list.

Supported carriers

JSON Format

couriers/*.json

Identifies the standard couriers that might send mail. Here is couriers/s10.json, shortened:

{
  "name": "S10 International Standard",
  "courier_code": "s10",
  "tracking_numbers": [
    {
      "id": "s10",
      "name": "S10",
      "description": "The UPU format every postal service uses for international items",
      "regex": "\\s*(?<ServiceType>([A-Z]\\s*){2})(?<SerialNumber>([0-9]\\s*){8})(?<CheckDigit>([0-9]\\s*))(?<CountryCode>([A-Z]\\s*){2})",
      "validation": {
        "checksum": { "name": "s10", "weightings": [8, 6, 4, 2, 3, 5, 9, 7], "modulo": 11 }
      },
      "glossary": {
        "SerialNumber": { "description": "Eight digits assigned by the issuing postal service." }
      },
      "tracking_url": null,
      "test_numbers": {
        "valid": ["RB123456785GB", "RB123456785US"],
        "invalid": ["RB123456786US", "RB123456785XX"]
      }
    }
  ]
}

Courier keys

KeyWhat it is
nameIdentifies the courier
courier_codeShort code to identify the courier. Alphanumeric only, no spaces.
tracking_numbersAn array of possible tracking number formats for this courier

Tracking number keys

KeyWhat it is
idIdentifies this format no matter what it gets renamed to. Both partner_id and the format's address on the site point back at this
nameA name to identify this type of tracking number. Usually includes the carrier in the name, i.e. FedExGround
regexA pcre compatible regular expression that identifies the tracking number regardless of spaces in-between characters. Either a string, or an array of strings to be concatenated (to help with readability).
description(optional) A note about the format itself, such as "USPS now calls this the IMpb barcode format"
glossary(optional) What this format's named groups mean when the general description isn't specific enough, keyed by group name
validationSpecifies how the tracking number is validated
additional(optional) Further information relating to a named regex group, such as a lookup table for the ServiceType group
partners(optional) A possible partnership between carriers, where one party is the shipper and the other the last mile carrier
tracking_urlA url that we can use to find the tracking history for a particular tracking number. It assumes the tracking number can be entered using python style string formatting "www.courier.com?trackingnumber=%s"
test_numbersvalid: an array of valid tracking numbers for testing, and invalid: an array of invalid tracking numbers for testing

Every regex must contain the named groups SerialNumber and CheckDigit and depending on the tracking number can optionally contain the following common attributes:

  • ServiceType: indicating the type of delivery service
  • ShipperId: indicating the shipper id
  • PackageId: indicating the package id
  • DestinationZip: indicating the destination zip code
validation

checksum: if the tracking number has a checksum, include a checksum key with the details. name specifies the algorithm. Supported algorithms are mod10, mod7, s10, luhn, mod_37_36 and sum_product_with_weightings_and_modulo.

"validation": {
  "checksum": {
    "name": "mod10",
    "evens_multiplier": 1,
    "odds_multiplier": 2
  }
}

Each checksum carries the constants its algorithm uses. Look at existing examples for parameters, or at CHECKSUM_ALGORITHMS.md for how each one works.

serial_number_format: some tracking numbers require some modification of the SerialNumber group before validation. In the example below, the serial number needs a "91" prepended before validation unless the number starts with a 91, 92, 93, 94, or 95

"serial_number_format": {
  "prepend_if": {
    "matches_regex": "^(?!9[1-5]).+",
    "content": "91"
  }
}

additional: some tracking numbers are only valid if one of their additional lookups finds a match. S10 requires a Courier, so a country code no postal service uses is invalid even with the right check digit.

"validation": {
  "additional": { "exists": ["Courier"] }
}
additional

A lookup table for the ServiceType regex group, relating the two digit letter code with the type of service:

"additional": [
  {
    "name": "Service Type",
    "regex_group_name": "ServiceType",
    "lookup": [
      { "matches": "01", "name": "UPS United States Next Day Air (Red)" },
      { "matches": "02", "name": "UPS United States Second Day Air (Blue)" }
    ]
  }
]

Each hash in the lookup array should contain a key called matches or matches_regex, specifying how the value of regex_group_name should be compared.

partners

Each entry describes a possible partnership between carriers, where one party is the shipper and the other the last mile carrier. A partnership only holds if both ends pass their checks against the same number. Each item in the partners array should have:

  • partner_id: (required) reference indicating the related definition
  • partner_type: (required) the relationship, either shipper or carrier
  • description: (optional) mainly for humans reading this
  • validation: (optional) a validation block deciding whether this partnership applies, either matches_all or matches_any, an array of match conditions each with a regex_group_name and either a matches or a matches_regex

glossary.json

What each part means, keyed by the regex group name. Anything reading couriers/*.json can then describe a SerialNumber the same way everything else does.

"ServiceType": {
  "label": "Service Type",
  "description": "A code for the delivery service used."
}

A definition's own glossary overrides the description when it can be more specific. For s10, the service type is two letters and the serial is eight digits assigned by the issuing postal service.

"glossary": {
  "ServiceType": {
    "description": "Two letters for the class of postal service, the first of which identifies the service and the second the variant."
  },
  "SerialNumber": {
    "description": "Eight digits assigned by the issuing postal service."
  }
}

Making a contribution

I'm adding or fixing a definition

  • Open an issue and specify the tracking numbers and courier service.
  • Modify or add definitions in the couriers/*.json files. Take a look at the existing ones, and follow the guidance above. Use https://trackingnumber.fyi for guidance on check digit algorithms if needed.
  • Run ./utils/lint_json.sh to clean up and validate the json file (you may need jq or other dependencies).
  • Run the tests locally. bundle exec rake If they pass, it's good, submit a PR!

The supported carriers table above is generated by CI and will update after a PR has been merged.

Reference

Contributors

jkeen

150 commits

adgaudio

49 commits

bramp

3 commits

jkeen/tracking_number_data

Shared data for cross platform tracking number detection

143

stars

237

commits

JavaScript

primary language

Sep 2, 2026

updated

trackingnumber.fyi/Browse cluster: Svelte UI components and design systems

README

Tests Release Semantic versioning Semantic release

Tracking Number Data

This repository contains json files that programmatically describe how to detect, validate, and decode tracking numbers. The collection started in the tracking_number ruby gem in 2010, and split out here in 2017 so that any language could use it.

trackingnumber.fyi consumes the latest release of this data. Paste a number in and it will tell you which carrier it belongs to and illustrate, digit by digit, what each part of that number means.

Libraries built on this data

Written one for a language that isn't listed? Open a PR to get it added to this list.

Supported carriers

JSON Format

couriers/*.json

Identifies the standard couriers that might send mail. Here is couriers/s10.json, shortened:

{
  "name": "S10 International Standard",
  "courier_code": "s10",
  "tracking_numbers": [
    {
      "id": "s10",
      "name": "S10",
      "description": "The UPU format every postal service uses for international items",
      "regex": "\\s*(?<ServiceType>([A-Z]\\s*){2})(?<SerialNumber>([0-9]\\s*){8})(?<CheckDigit>([0-9]\\s*))(?<CountryCode>([A-Z]\\s*){2})",
      "validation": {
        "checksum": { "name": "s10", "weightings": [8, 6, 4, 2, 3, 5, 9, 7], "modulo": 11 }
      },
      "glossary": {
        "SerialNumber": { "description": "Eight digits assigned by the issuing postal service." }
      },
      "tracking_url": null,
      "test_numbers": {
        "valid": ["RB123456785GB", "RB123456785US"],
        "invalid": ["RB123456786US", "RB123456785XX"]
      }
    }
  ]
}

Courier keys

KeyWhat it is
nameIdentifies the courier
courier_codeShort code to identify the courier. Alphanumeric only, no spaces.
tracking_numbersAn array of possible tracking number formats for this courier

Tracking number keys

KeyWhat it is
idIdentifies this format no matter what it gets renamed to. Both partner_id and the format's address on the site point back at this
nameA name to identify this type of tracking number. Usually includes the carrier in the name, i.e. FedExGround
regexA pcre compatible regular expression that identifies the tracking number regardless of spaces in-between characters. Either a string, or an array of strings to be concatenated (to help with readability).
description(optional) A note about the format itself, such as "USPS now calls this the IMpb barcode format"
glossary(optional) What this format's named groups mean when the general description isn't specific enough, keyed by group name
validationSpecifies how the tracking number is validated
additional(optional) Further information relating to a named regex group, such as a lookup table for the ServiceType group
partners(optional) A possible partnership between carriers, where one party is the shipper and the other the last mile carrier
tracking_urlA url that we can use to find the tracking history for a particular tracking number. It assumes the tracking number can be entered using python style string formatting "www.courier.com?trackingnumber=%s"
test_numbersvalid: an array of valid tracking numbers for testing, and invalid: an array of invalid tracking numbers for testing

Every regex must contain the named groups SerialNumber and CheckDigit and depending on the tracking number can optionally contain the following common attributes:

  • ServiceType: indicating the type of delivery service
  • ShipperId: indicating the shipper id
  • PackageId: indicating the package id
  • DestinationZip: indicating the destination zip code
validation

checksum: if the tracking number has a checksum, include a checksum key with the details. name specifies the algorithm. Supported algorithms are mod10, mod7, s10, luhn, mod_37_36 and sum_product_with_weightings_and_modulo.

"validation": {
  "checksum": {
    "name": "mod10",
    "evens_multiplier": 1,
    "odds_multiplier": 2
  }
}

Each checksum carries the constants its algorithm uses. Look at existing examples for parameters, or at CHECKSUM_ALGORITHMS.md for how each one works.

serial_number_format: some tracking numbers require some modification of the SerialNumber group before validation. In the example below, the serial number needs a "91" prepended before validation unless the number starts with a 91, 92, 93, 94, or 95

"serial_number_format": {
  "prepend_if": {
    "matches_regex": "^(?!9[1-5]).+",
    "content": "91"
  }
}

additional: some tracking numbers are only valid if one of their additional lookups finds a match. S10 requires a Courier, so a country code no postal service uses is invalid even with the right check digit.

"validation": {
  "additional": { "exists": ["Courier"] }
}
additional

A lookup table for the ServiceType regex group, relating the two digit letter code with the type of service:

"additional": [
  {
    "name": "Service Type",
    "regex_group_name": "ServiceType",
    "lookup": [
      { "matches": "01", "name": "UPS United States Next Day Air (Red)" },
      { "matches": "02", "name": "UPS United States Second Day Air (Blue)" }
    ]
  }
]

Each hash in the lookup array should contain a key called matches or matches_regex, specifying how the value of regex_group_name should be compared.

partners

Each entry describes a possible partnership between carriers, where one party is the shipper and the other the last mile carrier. A partnership only holds if both ends pass their checks against the same number. Each item in the partners array should have:

  • partner_id: (required) reference indicating the related definition
  • partner_type: (required) the relationship, either shipper or carrier
  • description: (optional) mainly for humans reading this
  • validation: (optional) a validation block deciding whether this partnership applies, either matches_all or matches_any, an array of match conditions each with a regex_group_name and either a matches or a matches_regex

glossary.json

What each part means, keyed by the regex group name. Anything reading couriers/*.json can then describe a SerialNumber the same way everything else does.

"ServiceType": {
  "label": "Service Type",
  "description": "A code for the delivery service used."
}

A definition's own glossary overrides the description when it can be more specific. For s10, the service type is two letters and the serial is eight digits assigned by the issuing postal service.

"glossary": {
  "ServiceType": {
    "description": "Two letters for the class of postal service, the first of which identifies the service and the second the variant."
  },
  "SerialNumber": {
    "description": "Eight digits assigned by the issuing postal service."
  }
}

Making a contribution

I'm adding or fixing a definition

  • Open an issue and specify the tracking numbers and courier service.
  • Modify or add definitions in the couriers/*.json files. Take a look at the existing ones, and follow the guidance above. Use https://trackingnumber.fyi for guidance on check digit algorithms if needed.
  • Run ./utils/lint_json.sh to clean up and validate the json file (you may need jq or other dependencies).
  • Run the tests locally. bundle exec rake If they pass, it's good, submit a PR!

The supported carriers table above is generated by CI and will update after a PR has been merged.

Reference

Contributors

jkeen

150 commits

adgaudio

49 commits

bramp

3 commits

Languages

JavaScript

48.6%

Svelte

33.1%

CSS

8.4%

Ruby

7.3%

Python

1.9%