Rexact
Cheatsheet

Regex German VAT number (USt-IdNr.)

The German intra-EU VAT number, or USt-IdNr., is written 'DE' followed by 9 digits: that is the structure published by the European Commission in the VIES service FAQ. The 9 digits end with a check digit computed with the ISO 7064 modulo 11,10 algorithm and, according to python-stdnum and jsvat, the first digit is never '0'. Among the four attempts read, validator.js makes the 'DE' prefix optional, so it accepts any string of 9 digits, and valvat accepts a leading zero. Here's an anchored pattern that requires the prefix and bounds the first digit, compared against those attempts; the check digit is not verified by the regex.

/^DE[1-9][0-9]{8}$/
passes 24/24 cases

Comparison of existing patterns

SourcepatternScore on the corpusReDoS
validator.js (isVAT, src/lib/isVAT.js) — préfixe « DE » facultatif : « 136695976 », sans pays, passe ; un zéro en tête (« DE036695976 ») passe aussi^(DE)?\d{9}$22 / 24safe
jsvat (germany.ts) — ancrée, préfixe obligatoire, premier chiffre de 1 à 9 : accepte exactement les mêmes chaînes que la recommandée ; la clé est contrôlée à part par calcFn, hors regex^(DE)([1-9]\d{8})$24 / 24safe
valvat (syntax.rb, A et Z remplacés par ^ et $) — ancrée, préfixe obligatoire, mais « DE036695976 » (zéro en tête) passe^DE[0-9]{9}$23 / 24safe
Regular Expressions Cookbook, recette 4.21 (une seule regex pour les 27 pays, insensible à la casse) — « 136695976 » nu et « de136695976 » passent, ainsi que « DK136695976 », lu comme une TVA française (2 caractères et 9 chiffres)^((AT)?U[0-9]{8}|(BE)?0[0-9]{9}|(BG)?[0-9]{9,10}|(CY)?[0-9]{8}L|(CZ)?[0-9]{8,10}|(DE)?[0-9]{9}|(DK)?[0-9]{8}|(EE)?[0-9]{9}|(EL|GR)?[0-9]{9}|(ES)?[0-9A-Z][0-9]{7}[0-9A-Z]|(FI)?[0-9]{8}|(FR)?[0-9A-Z]{2}[0-9]{9}|(GB)?([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3})|(HU)?[0-9]{8}|(IE)?[0-9]S[0-9]{5}L|(IT)?[0-9]{11}|(LT)?([0-9]{9}|[0-9]{12})|(LU)?[0-9]{8}|(LV)?[0-9]{11}|(MT)?[0-9]{8}|(NL)?[0-9]{9}B[0-9]{2}|(PL)?[0-9]{10}|(PT)?[0-9]{9}|(RO)?[0-9]{2,10}|(SE)?[0-9]{12}|(SI)?[0-9]{8}|(SK)?[0-9]{10})$20 / 24safe

Implementation

const re = new RegExp("^DE[1-9][0-9]{8}$", "");
re.test(input);

Limits

  • Valide seulement la FORME : « DE136695978 » a la bonne structure mais une clé fausse (ISO 7064 modulo 11,10) et passe ce motif. La clé n'est pas recalculée par la regex.
  • N'établit pas que le numéro est attribué : seule une interrogation de VIES (ou du BZSt) le confirme. Le numéro de TVA (USt-IdNr.) ne doit pas être confondu avec le Steuernummer, le numéro fiscal national, de format différent.
  • L'exclusion d'un premier chiffre « 0 » repose sur python-stdnum et jsvat (sources secondaires) ; elle n'est pas énoncée dans la FAQ de la Commission.
  • Pas de tolérance pour les espaces, tirets ou minuscules : normalisez (supprimer les séparateurs, mettre en majuscules) avant de valider. Les numéros du corpus sont synthétiques ; ne testez pas avec de vrais numéros de clients.

Related pages