Australian Medicare Provider Number Validation

Provider numbers are issued by Medicare Australia to general practitioners, consultants, specialists and allied health professionals. The numbers are issued to individuals (not practices) and a separate number is required for each distinct location where the provider practices.

Provider numbers (eg 4024742F ) have the following structure:

ComponentLengthValid Symbols
Stem 6 digitsdigits 0-9
Location Character 1 digit or alphabetic characterdigits 0-9 and characters except I, O, S and Z
Check Character 1 alphabetic characteronly A, B, F, H, J, K, L, T, W, X, Y

Note that the letters 'I','O','S' and 'Z' are not valid location characters (presumably due to the likelihood of confusion with similar-looking digits). Some documentation also incorrectly removes the digit '1' from this table, but '1' is a valid location code.

When calculating the check digit, the location character is translated into a numeric Practice Location Value (PLV) as follows.

Location
Character
PLVLocation
Character
PLV
00G16
11H17
22J18
33K19
44L20
55M21
66N22
77P23
88Q24
99R25
A10T26
B11U27
C12V28
D13W29
E14X30
F15Y31

The check character is calculated using the following formula, where PLV is the numeric value for the location digit determined in the table above.

R = ((digit 1x3) + (digit 2x5) + (digit 3x8) + (digit 4x4) + (digit 5x2) + (digit 6) + (PLV x 6)) % 11

The remainder R is in the range 0..10, and is then converted into an alpha check character using the following table:

RemainderCheck CharacterRemainderCheck Character
0Y6J
1X7H
2W8F
3T9B
4L10A
5K

Reference

This seems to be a secret. For a while the algorithm could be found here: http://www.medicareaustralia.gov.au/provider/vendors/files/acir-immunisation-document-formats.pdf but that's now gone.

As of Sept 2015 this document is only available in Google's cache: http://www.health.vic.gov.au/pcps/downloads/coordination/sctt_guide_vol3.pdf but be careful. It contains a definition of the algorithm with a couple of critical errors of ommission that would make it unimplementable.

Try It!

Incorrectly Issued Provder Numbers

In Sept 2015 a reader reported a provider number ending in an 'S' which failed validation - 'S' is not a valid checkdigit. Medicare initially insisted the number was correct, but eventually agreed the number had been incorrectly issued. So it can happen, and it sounds like it took some persistence to get it resolved.

Sample Code

//   ValidateMedicareProviderNumber
//     Checks medicare provider number for validity
//     using the published checksum algorithm.
//     Returns: true if the number is valid, false otherwise.
// 
//   Note - this allows for a leading 0 to be dropped, 
//     reducing the 6-digit stem to 5 digits.
//
//      Source: http://www.clearwater.com.au/code
//      Author: Guy Carpenter
//     License: The author claims no rights to this code.
//              Use it as you wish.

function ValidateMedicareProviderNumber($ProviderNumber)
{
    /*
     * The Medicare provider number comprises:
     *  - six digits (provider stem)
     *  -  a practice location character (one alphanum char)
     *  -  a check-digit (one alpha character)
     */

    $locTable = '0123456789ABCDEFGHJKLMNPQRTUVWXY';
    $checkTable = 'YXWTLKJHFBA';
    $weights = array(3,5,8,4,2,1);
    $re = "/^(\d{5,6})([{$locTable}])([{$checkTable}])$/";

    $providerNumber = preg_replace("/[^\dA-Z]/", 
                                   "",
                                   strtoupper($ProviderNumber));
    if (preg_match($re, $providerNumber, $matches)) {
        $stem = $matches[1];

        // accommodate dropping of leading 0 
        if (strlen($stem)==5) $stem="0".$stem;  

        $location = $matches[2];
        $checkDigit = $matches[3][0];
            
        // IMPORTANT - letters I, O, S and Z are not included 
        // Some documentation incorrectly removes the digit 1.
        $plv = strpos($locTable, $location);
        $sum = $plv * 6;

        foreach ($weights as $position=>$weight) {
            $sum += $stem[$position] * $weight;
        }

        if ($checkDigit == $checkTable[$sum % 11]) {
            return true;
        }
    }
    return false;
}

comments powered by Disqus