VIN Validation RegEx

I have written a VIN validation RegEx based on the but then when I try to run some tests it is not accepting some valid VIN Numbers.

My RegEx:

^[A-HJ-NPR-Za-hj-npr-z\\d]{8}[\\dX][A-HJ-NPR-Za-hj-npr-z\\d]{2}\\d{6}$

VIN Number Not Working:
1ftfw1et4bfc45903
WP0ZZZ99ZTS392124

VIN Numbers Working:
19uya31581l000000
1hwa31aa5ae006086

(I think the problem occurs with the numbers at the end, Wikipedia made it sound like it would end with only 6 numbers and the one that is not working but is a valid number only ends with 5)

Any Help Correcting this issue would be greatly appreciated!

2

8 Answers

I can't help you with a perfect regex for VIN numbers -- but I can explain why this one is failing in your example of 1ftfw1et4bfc45903:

^[A-HJ-NPR-Za-hj-npr-z\d]{8}[\dX][A-HJ-NPR-Za-hj-npr-z\d]{2}\d{6}$

Explanation:

  • ^[A-HJ-NPR-Za-hj-npr-z\d]{8}
    This allows for 8 characters, composed of any digits and any letters except I, O, and Q; it properly finds the first 8 characters:
    1ftfw1et
  • [\dX]
    This allows for 1 character, either a digit or a capital X; it properly finds the next character:
    4
  • [A-HJ-NPR-Za-hj-npr-z\d]{2}
    This allows for 2 characters, composed of any digits and any letters except I, O, and Q; it properly finds the next 2 characters:
    bf
  • \d{6}$
    This allows for exactly 6 digits, and is the reason the regex fails; because the final 6 characters are not all digits:
    c45903
0

Dan is correct - VINs have a checksum. You can't utilize that in regex, so the best you can do with regex is casting too wide of a net. By that I mean that your regex will accept all valid VINs, and also around a trillion (rough estimate) non-VIN 17-character strings.

If you are working in a language with named capture groups, you can extract that data as well.

So, if your goal is:

  • Only to not reject valid VINs (letting in invalid ones is ok) then use Fransisco's answer, [A-HJ-NPR-Z0-9]{17}.

  • Not reject valid VINs, and grab info like model year, plant code, etc, then use this (note, you must use a language that can support named capture groups - off the top of my head: Perl, Python, Elixir, almost certainly others but not JS): /^(?<wmi>[A-HJ-NPR-Z\d]{3})(?<vds>[A-HJ-NPR-Z\d]{5})(?<check>[\dX])(?<vis>(?<year>[A-HJ-NPR-Z\d])(?<plant>[A-HJ-NPR-Z\d])(?<seq>[A-HJ-NPR-Z\d]{6}))$/ where the names are defined at the end of this answer.

  • Not reject valid VINs, and prevent some but not all invalid VINs, you can get specific like Pedro does.

  • Only accept valid VINs: you need to write code (just kidding, GitHub exists).

Capture group name key:

  • wmi - World manufacturer identifier
  • vds - Vehicle descriptor section
  • check - Check digit
  • vis - Vehicle identifier section
  • year - Model year
  • plant - Plant code
  • seq - Production sequence number
1

This regular expression is working fine for validating US VINs, including the one you described:

[A-HJ-NPR-Z0-9]{17}

Remember to make it case insensitive with flag i

Source:

VIN should have only A-Z, 0-9 characters, but not I, O, or Q
Last 6 characters of VIN should be a number
VIN should be 17 characters long

You didn't specify which language you're using but the following regex can be used to validate a US VIN with php:

/^(?:([A-HJ-NPR-Z]){3}|\d{3})(?1){2}\d{2}(?:(?1)|\d)(?:\d|X)(?:(?1)+\d+|\d+(?1)+)\d{6}$/i
5

I feel regex is not the ideal validation. VINs have a built in check digit. (VIN_codes)/Check_digit or

I suggest you build an algorithm using this. (Untested algorithm example)

This should work, it is from splunk search, so there are some additional exclusions**

(?i)(?<VIN>[A-Z0-9^IOQioq_]{11}\d{6})

The NHTSA website provides the method used to calculate the 9th character checksum, if you're interested. It also provides lots of other useful data, such as which characters are allowed in which position, or how to determine whether the 10th character, if alphabetic, refers to a model year up to 1999 or a model year from 2010.

NHTSA VIN eCFR

Hope that helps.

1

Please, use this regular expression. It is shorter and works with all VIN types

(?=.*\d|[A-Z])(?=.*[A-Z])[A-Z0-9]{17}

I changed above formula by new below formula

(?=.*\d|=.*[A-Z])(?=.*[A-Z])[A-Z0-9]{17}

This regular expression consider any letter but at leats one digit, max 17 characters

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like