Regex Indian GSTIN (tax number)
A GSTIN has 15 characters: 2 state-code digits, the taxpayer's 10-character PAN, an entity counter (1 to 9 then A to Z), a 'Z' and a modulo 36 check. The state code runs from 01 to 38 (Zoho's list, a third-party source, adds 97); the PAN's 4th character is the holder type, a letter among A B C F G H J L P T (tax authority's TRACES page). The three real attempts I read accept almost any leading digit pair: '00AAAPL1234C1ZU' and '39AAAPL1234C1Z9' pass, as does '27AAADE1234C1ZA', whose holder type 'D' does not exist. One is even copied as-is from a README, unanchored. Here's a pattern bounding the state code and the PAN type, compared against those attempts.
/^(?:0[1-9]|[12][0-9]|3[0-8]|97)[A-Z]{3}[ABCFGHJLPT][A-Z][0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/passes 22/22 cases
Comparison of existing patterns
| Source | pattern | Score on the corpus | ReDoS |
|---|---|---|---|
| gstin-validator (npm) — ancrée, code d'État jusqu'à 38 et type de PAN, mais « [0-2][0-9] » accepte 00, le type « K » (absent de la liste de l'administration) est accepté et « 0 » en 13e position aussi ; rejette 97 | ^([0-2][0-9]|[3][0-8])[A-Z]{3}[ABCFGHLJPTK][A-Z]\d{4}[A-Z][A-Z0-9][Z][A-Z0-9]$ | 19 / 22 | safe |
| @ashwinbande/validators (npm) — ancrée mais « \d{2} » : n'importe quel code d'État (« 00 », « 39 ») ; aucun contrôle du type de PAN (« 27AAADE1234C1ZA » passe) | ^\d{2}[A-Z]{5}\d{4}[A-Z][A-Z\d][Z][A-Z\d]$ | 18 / 22 | safe |
| tk120404/gst (README, même regex que la réponse à 58 votes de Stack Overflow) — pas d'ancres : « XX27AAAPL1234C1ZE99 » passe ; aucun code d'État ni type de PAN contrôlé | \d{2}[A-Z]{5}\d{4}[A-Z]{1}[A-Z\d]{1}[Z]{1}[A-Z\d]{1} | 16 / 22 | safe |
Implementation
const re = new RegExp("^(?:0[1-9]|[12][0-9]|3[0-8]|97)[A-Z]{3}[ABCFGHJLPT][A-Z][0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$", "");
re.test(input);Limits
- Valide seulement la FORME : ne calcule pas la clé modulo 36. « 27AAAPL1234C1Z0 » a la bonne forme mais une clé fausse et passe ce motif. Le 5e caractère du PAN (initiale du nom) et l'existence du contribuable ne peuvent pas être vérifiés par une regex.
- Les règles « Z » en 14e position, « 13e caractère de 1 à 9 ou A à Z » et la clé viennent de python-stdnum et d'autres sources secondaires, pas des CGST Rules, qui ne fixent que la composition (code d'État, PAN, code d'entité, clé). Les codes d'État 25 et 28 sont acceptés, bien que la liste de la Zoho ne les cite pas : la liste officielle n'a pas pu être consultée.
- Le type de titulaire du PAN (4e caractère) est limité à A B C F G H J L P T, d'après la page TRACES ; « K », que certaines bibliothèques acceptent, est rejeté. Le code d'État 99 (juridiction centrale) et 96 ne sont pas acceptés.
- L'algorithme de la clé du PAN lui-même n'est pas public : le PAN n'est vérifié que pour sa forme. Les numéros du corpus, hors les deux exemples de bibliothèques, sont synthétiques avec une clé recalculée ; n'utilisez pas de vrais GSTIN dans vos tests.