Regex Brazilian phone number
A Brazilian number has a 2-digit DDD (area code), then 9 digits starting with 9 (mobile) or 8 digits starting with 2 to 5 (landline). Not all DDDs from 11 to 99 exist: 10, 20, 23, 25, 26, 29... do not. The real attempts I read accept almost anything that looks like two digits: the Drupal 'phone' module accepts '(10) 91234-5678' and '(11) 81234-5678', LaravelLegends's regex requires parentheses around the DDD and rejects '11961234567', and validator.js accepts a landline starting with 1 or 6. Here's a pattern bounding the DDD and the first digit of the number, compared against those attempts.
/^(?:\+?55 ?)?\(?0?(?:[14689][1-9]|2[12478]|3[1-578]|5[13-5]|7[13-579])\)? ?(?:9[0-9]{4}|[2-5][0-9]{3})-?[0-9]{4}$/passes 26/26 cases
Comparison of existing patterns
| Source | pattern | Score on the corpus | ReDoS |
|---|---|---|---|
| validator.js (pt-BR) — DDD [1-9]{2} : « 23 » ou « 91 » passent ; la branche « \d{4}-?\d{4} » accepte un fixe commençant par 1 ou 6 et un mobile à 8 chiffres ancien format (« (11) 9123-4567 ») | ^((\+?55\ ?[1-9]{2}\ ?)|(\+?55\ ?\([1-9]{2}\)\ ?)|(0[1-9]{2}\ ?)|(\([1-9]{2}\)\ ?)|([1-9]{2}\ ?))((\d{4}\-?\d{4})|(9[1-9]{1}\d{3}\-?\d{4}))$ | 21 / 26 | safe |
| LaravelLegends/pt-br-validator (CelularComDdd) — parenthèses obligatoires autour du DDD : rejette « 11961234567 », « +55 11 96123-4567 » ; accepte « (00) 91234-5678 », « (10) … », « (23) … » et « (11) 1234-5678 » | ^\(\d{2}\)\s?\d{4,5}-\d{4}$ | 11 / 26 | safe |
| Drupal phone (7.x-1.x, phone.br.inc) — DDD « 0?[1-9][0-9] » : accepte 10, 20, 23 et tout numéro de 3 à 5 chiffres suivi de 4 : « (11) 81234-5678 », « (11) 1234-5678 », « (11) 6234-5678 » passent | ^(\+|0{2}|)?(55|0|)[\s.-]?((\(0?[1-9][0-9]\))|(0?[1-9][0-9]))[\s.-]?([1-9][0-9]{2,4})[\s.-]?([0-9]{4})$ | 19 / 26 | safe |
Implementation
const re = new RegExp("^(?:\\+?55 ?)?\\(?0?(?:[14689][1-9]|2[12478]|3[1-578]|5[13-5]|7[13-579])\\)? ?(?:9[0-9]{4}|[2-5][0-9]{3})-?[0-9]{4}$", "");
re.test(input);Limits
- Valide seulement la FORME : ne vérifie pas que le numéro est attribué. La liste des DDD existants et les règles de premier chiffre viennent des métadonnées de libphonenumber, pas d'un texte d'ANATEL que je n'ai pas relu (la résolution actuelle, 749/2022, remplace celle de 2010).
- Le mobile est modélisé comme « 9 + 8 chiffres » ; libphonenumber accepte encore des numéros de 8 chiffres commençant par 7 (« (11) 7123-4567 »), qui sont rejetés ici. Le zéro de tronc (« 011 »…) est accepté avant le DDD, avec ou sans parenthèses.
- Accepte le préfixe +55 ou 55 facultatif, des parenthèses facultatives autour du DDD, une espace facultative et un tiret facultatif avant les 4 derniers chiffres. Les extensions et les formes avec points sont rejetées.
- Aucune plage fictive officielle n'existe ; sauf les deux exemples de libphonenumber, les numéros du corpus sont synthétiques et ne correspondent à aucun abonné par construction.