RRegexBuilder
Get RegexBuilder

RegexBuilder · regex answers

Regex for a credit card number

/^(?:4\d{12}(?:\d{3})?|5[1-5]\d{14}|2(?:22[1-9]|2[3-9]\d|[3-6]\d{2}|7[01]\d|720)\d{12}|3[47]\d{13}|6(?:011\d{12}|5\d{14}|4[4-9]\d{13}|22(?:12[6-9]|1[3-9]\d|[2-8]\d{2}|9[01]\d|92[0-5])\d{10}))$/

This recognises the brand prefixes and lengths for Visa, Mastercard (both the 51-55 range and the 2221-2720 range issued since 2017), American Express and Discover (6011, 65, 644-649 and 622126-622925). It cannot tell you the number is real — that is the Luhn checksum. It is not literally beyond regular expressions — over a fixed length the language is finite, so an automaton with ten states decides it — but the expanded pattern grows about a hundredfold every two digits, so at sixteen digits it is astronomically large. Impractical, not impossible: do the arithmetic in code. Strip spaces and hyphens before testing.

What each part does

4\d{12}(?:\d{3})?Visa: starts with 4, thirteen or sixteen digits
5[1-5]\d{14}Mastercard: the original 51-55 range, sixteen digits
2(?:22[1-9]|2[3-9]\d|[3-6]\d{2}|7[01]\d|720)\d{12}Mastercard: the 2221-2720 range it has issued since 2017 — omit it and a large share of real cards is rejected
3[47]\d{13}American Express: 34 or 37, fifteen digits
6(?:011\d{12}|5\d{14}|4[4-9]\d{13}|22(?:12[6-9]|1[3-9]\d|[2-8]\d{2}|9[01]\d|92[0-5])\d{10})Discover: 6011, 65xx, 644-649 and 622126-622925 — the last two are real issuing ranges, and leaving them out silently declines live cards

Tested against real input

Every row below was run through the engine when this page was built. The third column is the substring the pattern actually matched.

InputResultMatched
4111111111111111matches4111111111111111
5500005555555559matches5500005555555559
2221000000000009matches2221000000000009
371449635398431matches371449635398431
6440000000000005matches6440000000000005
4111 1111 1111 1111no match
1234567890123456no match
411111111111no match

The mistake to avoid

Shipping this as validation. Without a Luhn check you accept 4111111111111112, and every payment processor will reject it after the user has already left the form.

Try it on your own text

Paste this pattern and your input, see each match highlighted with its capture groups, step through what the engine did, and get the equivalent syntax for JavaScript, Python, Java, Go and PCRE.

Open RegexBuilder

Other regex answers