Dev.to WebDev 🛠 Dev 👁 0 📖 2 min read

How to Read a VIN: WMI, VDS, VIS and the Check Digit Explained

Every car built for the North American market since 1981 carries a 17-character Vehicle Identification Number (VIN). It looks random, but it's a structured record defined by ISO 3779 and U.S. regulation 49 CFR Part 565.

Every car built for the North American market since 1981 carries a 17-character Vehicle Identification Number (VIN). It looks random, but it's a structured record defined by ISO 3779 and U.S. regulation 49 CFR Part 565. Here's how to read it.

The three sections

A VIN splits into three parts:

Positions Name Meaning
1-3 WMI World Manufacturer Identifier
4-9 VDS Vehicle Descriptor Section (includes check digit)
10-17 VIS Vehicle Identifier Section

Example: 1HGCM82633A004352

WMI (positions 1-3)

  • Position 1 is the region/country of manufacture: 1, 4, 5 = USA, 2 = Canada, 3 = Mexico, J = Japan, K = South Korea, W = Germany.
  • Positions 2-3 identify the manufacturer and often vehicle type. 1HG = Honda (USA-built passenger car).

Small manufacturers (under 1,000 vehicles/year) use a 9 in position 3 and get an extra code in positions 12-14.

VDS (positions 4-9)

Positions 4-8 are manufacturer-defined: model line, body style, engine, restraint system. You can't decode these without the manufacturer's spec, which is why tools rely on NHTSA's vPIC database, where manufacturers file their VIN patterns.

Position 9 is the check digit. Each character is transliterated to a number (letters I, O, Q are never allowed), multiplied by a position weight (8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2), summed, and taken mod 11. A remainder of 10 becomes X.

const map = {A:1,B:2,C:3,D:4,E:5,F:6,G:7,H:8,J:1,K:2,L:3,M:4,N:5,P:7,R:9,S:2,T:3,U:4,V:5,W:6,X:7,Y:8,Z:9};
const w = [8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2];
function validVin(vin) {
  vin = vin.toUpperCase();
  if (!/^[A-HJ-NPR-Z0-9]{17}$/.test(vin)) return false;
  const sum = [...vin].reduce((s, c, i) => s + (isNaN(c) ? map[c] : +c) * w[i], 0);
  const r = sum % 11;
  return vin[8] === (r === 10 ? 'X' : String(r));
}

VIS (positions 10-17)

  • Position 10 is the model year: A-Y (skipping I, O, Q, U, Z) and 1-9, cycling every 30 years. 3 = 2003 or 2033; position 7 helps disambiguate for newer vehicles.
  • Position 11 is the assembly plant (manufacturer-defined).
  • Positions 12-17 are the production sequence number.

Why it matters

When buying used, a decoded VIN that doesn't match the listing (wrong year, engine, or body) is a red flag. A failed check digit can mean a typo or a tampered plate.

You can query NHTSA's free vPIC API directly:

https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVinValues/1HGCM82633A004352?format=json

Disclosure: I build VIN Lookup, a free decoder on top of NHTSA vPIC data.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.