Below are regular expressions useful for common validation scenarios. No claim is made that they are complete or perfect (please comment if you see a flaw and I will update). I also can’t claim authorship of most of these – they were liberally lifted from elsewhere
URL
^((((https?|ftps?|gopher|telnet|nntp)://)|(mailto:|news:))(%[0-9A-Fa-f]{2}|[-()_.!~*';/?:@&=+$,A-Za-z0-9])+)([).!';/?:,][[:blank:]])?$
IPv4 IP
\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
IPv6 IP
(?<![:.\w])(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}(?![:.\w])
Email Address
^[\w\-\+\&\*]+(?:\.[\w\-\_\+\&\*]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}$
Credit Card
|
All Major Cards |
bare | ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$ |
| Grouped | ^(?:4\d{3}[ -]*\d{4}[ -]*\d{4}[ -]*\d(?:\d{3})?|5[1-5]\d{2}[ -]*\d{4}[ -]*\d{4}[ -]*\d{4}|6(?:011|5[0-9]{2})[ -]*\d{4}[ -]*\d{4}[ -]*\d{4}|3[47]\d{2}[ -]*\d{6}[ -]*\d{5}|3(?:0[0-5]|[68][0-9])\d[ -]*\d{6}[ -]*\d{4}|(?:2131|1800)[ -]*\d{6}[ -]*\d{5}|35\d{2}[ -]*\d{4}[ -]*\d{4}[ -]*\d{4})$ | |
| Spaces/dashes | ^[ -]*(?:4[ -]*(?:\d[ -]*){11}(?:(?:\d[ -]*){3})?\d|5[ -]*[1-5](?:[ -]*[0-9]){14}|6[ -]*(?:0[ -]*1[ -]*1|5[ -]*\d[ -]*\d)(?:[ -]*[0-9]){12}|3[ -]*[47](?:[ -]*[0-9]){13}|3[ -]*(?:0[ -]*[0-5]|[68][ -]*[0-9])(?:[ -]*[0-9]){11}|(?:2[ -]*1[ -]*3[ -]*1|1[ -]*8[ -]*0[ -]*0|3[ -]*5(?:[ -]*[0-9]){3})(?:[ -]*[0-9]){11})[ -]*$ | |
|
All Major Cards, Named |
bare | ^(?:
(?<visa>4[0-9]{12}(?:[0-9]{3})?) | (?<mastercard>5[1-5][0-9]{14}) | (?<discover>6(?:011|5[0-9][0-9])[0-9]{12}) | (?<amex>3[47][0-9]{13}) | (?<diners>3(?:0[0-5]|[68][0-9])[0-9]{11}) | (?<jcb>(?:2131|1800|35\d{3})\d{11}) )$ |
| Grouped | ^(?:
(?<visa>4\d{3}[ -]*\d{4}[ -]*\d{4}[ -]*\d(?:\d{3})?) | (?<mastercard>5[1-5]\d{2}[ -]*\d{4}[ -]*\d{4}[ -]*\d{4}) | (?<discover>6(?:011|5[0-9]{2})[ -]*\d{4}[ -]*\d{4}[ -]*\d{4}) | (?<amex>3[47]\d{2}[ -]*\d{6}[ -]*\d{5}) | (?<diners>3(?:0[0-5]|[68][0-9])\d[ -]*\d{6}[ -]*\d{4}) | (?<jcb>(?:2131|1800)[ -]*\d{6}[ -]*\d{5}|35\d{2}[ -]*\d{4}[ -]*\d{4}[ -]*\d{4}) )$ |
|
| Spaces/dashes | ^[ -]*(?:
(?<visa>4[ -]*(?:\d[ -]*){11}(?:(?:\d[ -]*){3})?\d) | (?<mastercard>5[ -]*[1-5](?:[ -]*[0-9]){14}) | (?<discover>6[ -]*(?:0[ -]*1[ -]*1|5[ -]*\d[ -]*\d)(?:[ -]*[0-9]){12}) | (?<amex>3[ -]*[47](?:[ -]*[0-9]){13}) | (?<diners>3[ -]*(?:0[ -]*[0-5]|[68][ -]*[0-9])(?:[ -]*[0-9]){11}) | (?<jcb>(?:2[ -]*1[ -]*3[ -]*1|1[ -]*8[ -]*0[ -]*0|3[ -]*5(?:[ -]*[0-9]){3})(?:[ -]*[0-9]){11}) )[ -]*$ |
|
|
American Express |
bare | ^3[47][0-9]{13}$ |
| Grouped | ^3[47]\d{2}[ -]*\d{6}[ -]*\d{5}$ | |
| Spaces/dashes | ^[ -]*3[ -]*[47][ -]*(?:\d[ -]*){13}$ | |
|
Diner’s Club |
bare | ^3(?:0[0-5]|[68][0-9])[0-9]{11}$ |
| Grouped | ^3(?:0[0-5]|[68][0-9])\d[ -]*\d{6}[ -]*\d{4}$ | |
| Spaces/dashes | ^[ -]*3[ -]*(?:0[ -]*[0-5]|[68][ -]*[0-9])[ -]*(?:\d[ -]*){11}$ | |
|
Discover |
bare | ^6(?:011|5[0-9]{2})[0-9]{12}$ |
| Grouped | ^6(?:011|5[0-9]{2})[ -]*\d{4}[ -]*\d{4}[ -]*\d{4}$ | |
| Spaces/dashes | ^[ -]*6[ -]*(?:0[ -]*1[ -]*1|5[ -]*\d[ -]*\d)[ -]*(?:\d[ -]*){12}$ | |
|
JCB |
bare | ^(?:2131|1800|35\d{3})\d{11}$ |
| Grouped | ^(?:(?:2131|1800)[ -]*\d{6}[ -]*\d{5}|35\d{2}[ -]*\d{4}[ -]*\d{4}[ -]*\d{4})$ | |
| Spaces/dashes | ^[ -]*(?:2[ -]*1[ -]*3[ -]*1|1[ -]*8[ -]*0[ -]*0|3[ -]*5(?:[ -]*\d){3})[ -]*(?:\d[ -]*){11}$ | |
|
Master Card |
bare | ^5[1-5][0-9]{14}$ |
| Grouped | ^5[1-5]\d{2}[ -]*\d{4}[ -]*\d{4}[ -]*\d{4}$ | |
| Spaces/dashes | ^[ -]*5[ -]*[1-5][ -]*(?:[0-9][ -]*){14}$ | |
|
Visa |
bare | ^4[0-9]{12}(?:[0-9]{3})?$ |
| Grouped | ^4\d{3}[ -]*\d{4}[ -]*\d{4}[ -]*\d(?:\d{3})?$ | |
| Spaces/dashes | ^[ -]*4[ -]*(?:\d[ -]*){12}(?:(?:\d[ -]*){3})?$ |
The following Regular Expression can remove all non-numeric characters from a credit card, to put it in the “bare” format above: [^0-9]+
National ID
| Austrian SSN | \b\d{4}(?:0[1-9]|[12]\d|3[01])(?:0[1-9]|1[0-5])\d{2}\b |
| Bulgarian UCN | \b\d{2}(?:[024][1-9]|[135][0-2])(?:0[1-9]|[12]\d|3[01])[-+]?\d{4}\b |
| Canadian SIN | \b[1-9]\d{2}[- ]?\d{3}[- ]?\d{3}\b |
| Chinese CNICN | \b\d{6}(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{4}\b |
| Croatian MCN | \b(?:0[1-9]|[12]\d|3[01])(?:0[1-9]|1[0-2])(?:9\d{2}|0[01]\d)\d{6}\b |
| Danish CRN | \b(?:0[1-9]|[12]\d|3[01])(?:0[1-9]|1[0-2])\d{2}[-+]?\d{4}\b |
| Finish SSN | \b(?:0[1-9]|[12]\d|3[01])(?:0[1-9]|1[0-2])\d{2}[-+a]\d{3}[a-z0-9]\b |
| Indian PAN | \b[a-z]{3}[abcfghjlpt][a-z]\d{4}[a-z]\b |
| Italian FC | \b(?:[bcdfghj-np-tv-z][a-z]{2}){2}\d{2}[a-ehlmprst](?:[04][1-9]|[1256]\d|[37][01])(?:\d[a-z]{3}|z\d{3})[a-z]\b |
| Norwegian SSN | \b(?:0[1-9]|[12]\d|3[01])(?:[04][1-9]|[15][0-2])\d{7}\b |
| Romanian PNC | \b[1-8]\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])(?:0[1-9]|[1-4]\d|5[0-2]|99)\d{4}\b |
| South Korean RRN | \b\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])-[0-49]\d{6}\b |
| Swedish PIN | \b(?:19|20)?\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])[-+]?\d{4}\b |
| Taiwanese NICN | \b[a-z][12]\d{8}\b |
| UK NIN | \b[abceghj-prstw-z][abceghj-nprstw-z] ?\d{2} ?\d{2} ?\d{2} ?[a-dfm]?\b |
| US SSN | \b(?!000)(?!666)(?:[0-6]\d{2}|7(?:[0-356]\d|7[012]))[- ](?!00)\d{2}[- ](?!0000)\d{4}\b |
US Phone Number
\(?\b[0-9]{3}\)?[-. ]?[0-9]{3}[-. ]?[0-9]{4}\b
The above regex matches 2223334444, 222 333 4444, 222-333-4444, 222.333.4444, (222) 333 4444 and all permutations thereof. For better granularity break the area code, prefix, and suffix into three different form fields so that only numbers need to be validated, not the format they were delivered in.
US Zip Code
\b[0-9]{5}(?:-[0-9]{4})?\b
VAT Number
| Austria | ^(AT)?U[0-9]{8}$ |
| Belgium | ^(BE)?0?[0-9]{9}$ |
| Bulgaria | ^(BG)?[0-9]{9,10}$ |
| Cyprus | ^(CY)?[0-9]{8}L$ |
| Czech Republic | ^(CZ)?[0-9]{8,10}$ |
| Denmark | ^(DK)?[0-9]{8}$ |
| Estonia | ^(EE)?[0-9]{9}$ |
| Finland | ^(FI)?[0-9]{8}$ |
| France | ^(FR)?[0-9A-Z]{2}[0-9]{9}$ |
| Germany | ^(DE)?[0-9]{9}$ |
| Greece | ^(EL|GR)?[0-9]{9}$ |
| Hungary | ^(HU)?[0-9]{8}$ |
| Ireland | ^(IE)?[0-9]S[0-9]{5}L$ |
| Italy | ^(IT)?[0-9]{11}$ |
| Latvia | ^(LV)?[0-9]{11}$ |
| Lithuania | ^(LT)?([0-9]{9}|[0-9]{12})$ |
| Luxembourg | ^(LU)?[0-9]{8}$ |
| Malta | ^(MT)?[0-9]{8}$ |
| Netherlands | ^(NL)?[0-9]{9}B[0-9]{2}$ |
| Poland | ^(PL)?[0-9]{10}$ |
| Portugal | ^(PT)?[0-9]{9}$ |
| Romania | ^(RO)?[0-9]{2,10}$ |
| Slovakia | ^(SK)?[0-9]{10}$ |
| Slovenia | ^(SI)?[0-9]{8}$ |
| Spain | ^(ES)?[0-9A-Z][0-9]{7}[0-9A-Z]$ |
| Sweden | ^(SE)?[0-9]{12}$ |
| UK | ^(GB)?([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3})$ |
Date
It is easiest to validate the date if the day, month, and year are broken up into three separate explicit fields. Not only does that simplify the regex used for validation, it removes ambiguity as to whether the day or month is first.
| d/m/yy and dd/mm/yyyy | \b(0?[1-9]|[12][0-9]|3[01])[- /.](0?[1-9]|1[012])[- /.](19|20)?[0-9]{2}\b |
| dd/mm/yyyy | (0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)[0-9]{2} |
| m/d/yy and mm/dd/yyyy | \b(0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2}\b |
| mm/dd/yyyy | (0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)[0-9]{2} |
| yy-m-d or yyyy-mm-dd | \b(19|20)?[0-9]{2}[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])\b |
| yyyy-mm-dd | (19|20)[0-9]{2}[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01]) |