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.
| Input | Result | Matched |
|---|---|---|
| 4111111111111111 | matches | 4111111111111111 |
| 5500005555555559 | matches | 5500005555555559 |
| 2221000000000009 | matches | 2221000000000009 |
| 371449635398431 | matches | 371449635398431 |
| 6440000000000005 | matches | 6440000000000005 |
| 4111 1111 1111 1111 | no match | — |
| 1234567890123456 | no match | — |
| 411111111111 | no 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 RegexBuilderOther regex answers
- Regex for an email address
- Regex for a US phone number
- Regex for an IPv4 address
- Regex for a URL
- Regex for a date in YYYY-MM-DD format
- Regex to match digits only
- Regex for alphanumeric characters
- Regex to find special characters
- Regex for a strong password
- Regex to match whitespace
- Regex to trim leading and trailing whitespace
- Regex for a UUID