npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ua-plates

v1.0.0

Published

Tiny zero-dependency parser for Ukrainian vehicle registration plates: Cyrillic-lookalike normalization, format/type detection (civilian, police, military, diplomatic, trailer, temporary, vanity) and region decoding by series.

Readme

ua-plates

Tiny zero-dependency TypeScript/ESM parser for Ukrainian vehicle registration plates: normalization of Cyrillic-lookalike spellings, format & type detection (civilian, trailer, police, military, diplomatic, temporary, vanity) and region decoding by the two-letter series.

Built for trustcar.info — a free Ukrainian license-plate encyclopedia. See any plate live at trustcar.info/plate/AA1234BC.

Ukrainian plates only use the 12 letters whose glyphs exist in both Cyrillic and Latin (А В С Е Н І К М О Р Т Х = A B C E H I K M O P T X), so the same plate gets typed both ways. This library folds everything to one canonical Latin form and decodes what the series means. The series → region map was verified against ~180k real registrations from the official data.gov.ua vehicle register, not just copied from reference tables.

Install

npm install ua-plates

Quickstart

import { parsePlate, isValidPlate, normalizePlate, regionBySeries } from "ua-plates";

normalizePlate("ах 1234 ор");   // "AX1234OP"  (Cyrillic → Latin, uppercase, no separators)

parsePlate("АА 1234 ВС");
// {
//   normalized: "AA1234BC",
//   valid: true,
//   format: "2015",
//   type: "civilian",
//   series: "AA",
//   digits: "1234",
//   region: { code: "AA", uk: "м. Київ", en: "Kyiv" }
// }

parsePlate("АВ 5936 ХР").type;  // "trailer"     (X-suffixes are reserved for trailers)
parsePlate("Т1 0079 АН").type;  // "temporary"   (T0–T9 dealer/transit series)
parsePlate("D123456").type;     // "diplomatic"
isValidPlate("5012");           // false         (bare fleet number, not a plate)
regionBySeries("КІ");           // { code: "KI", uk: "Київська обл.", en: "Kyiv Oblast" }

API

| Export | Signature | Description | |--------|-----------|-------------| | normalizePlate | (raw: string) => string | Pure text transform: trim, drop separators (spaces/hyphens/dots/underscores), uppercase, map the 12 Cyrillic lookalikes to Latin. No validation. | | parsePlate | (raw: string) => ParsedPlate \| null | Full parse: { normalized, valid, format, type, series, digits, region }. Returns null for empty input or characters that can never appear on a plate; returns { valid: false, ... } for alphanumeric strings that match no known structure. | | isValidPlate | (raw: string) => boolean | Shortcut for parsePlate(raw)?.valid === true. | | regionBySeries | (series: string) => { code, uk, en } \| null | Resolve a two-letter series (Latin or Cyrillic, any case) to its region. | | UA_PLATE_REGIONS | readonly { codes, uk, en }[] | The full series → region dataset: 27 regions, 54 codes (first + second series). |

Recognized formats and types

| Pattern (normalized) | format | type | Example | Notes | |---|---|---|---|---| | LL dddd LL | 2015 | civilian | AA1234BC | DSTU 4278:2004 standard (2015 redesign kept the layout). Region from the first pair. | | LL dddd XL | 2015 | trailer | AB5936XP | X-starting suffixes (XX, XT, XP, XO…) are reserved for trailers/semi-trailers. | | Td dddd LL | special | temporary | T10079AH | Red dealer/transit plates, series T0–T9 (also the agricultural TP dddd LL). | | LL dddd L | special | police | AA1234M | Blue National Police plates; region letters first. | | dddd Ld | special | military | 1234A1 | Armed Forces: four digits + letter + digit. | | D dddddd, CDP/DP/CC/S + digits | special | diplomatic | D123456, DP12345 | Current D-series and former CDP/DP/CC/S series. | | ddddd LL | legacy | civilian | 12345KA | 1995 standard («123-45 КА»). | | dddd LL | legacy | moto | 3678XB | Legacy motorcycle / light-trailer shape. | | dd LL dddd | legacy | trailer | 05XX5132 | Legacy trailer with numeric region prefix. | | anything else, 3–8 chars, ≥2 letters | special | vanity | BATMAN | Owner-chosen individual plates (and unclassifiable old plates). |

L = one of the 12 plate letters, d = digit.

Caveats. Plate color isn't part of the string, so text-only classification of police/military/temporary is heuristic — a 7-char vanity plate shaped like LL dddd L will read as police. Modern motorcycle plates use the same LL dddd LL layout as cars (only the physical plate is square), so they parse as civilian; moto is only reported for the legacy shape. A structurally valid plate with an unknown series (e.g. the nationwide II series or future allocations) parses as civilian with region: null.

Region codes

27 regions × 2 series = 54 codes. Second series (K/H/I prefix) were rolled out as regions exhausted their first ranges. IA, IH, KK are allocated but not yet observed in circulation (Cherkasy hasn't exhausted CA; Crimea/Sevastopol issuance froze in 2014).

| Series | Region (uk) | Region (en) | |--------|-------------|-------------| | AA, KA | м. Київ | Kyiv | | AB, KB | Вінницька обл. | Vinnytsia | | AC, KC | Волинська обл. | Volyn | | AE, KE | Дніпропетровська обл. | Dnipropetrovsk | | AH, KH | Донецька обл. | Donetsk | | AI, KI | Київська обл. | Kyiv Oblast | | AK, KK | АР Крим | Crimea | | AM, KM | Житомирська обл. | Zhytomyr | | AO, KO | Закарпатська обл. | Zakarpattia | | AP, KP | Запорізька обл. | Zaporizhzhia | | AT, KT | Івано-Франківська обл. | Ivano-Frankivsk | | AX, KX | Харківська обл. | Kharkiv | | BA, HA | Кіровоградська обл. | Kirovohrad | | BB, HB | Луганська обл. | Luhansk | | BC, HC | Львівська обл. | Lviv | | BE, HE | Миколаївська обл. | Mykolaiv | | BH, HH | Одеська обл. | Odesa | | BI, HI | Полтавська обл. | Poltava | | BK, HK | Рівненська обл. | Rivne | | BM, HM | Сумська обл. | Sumy | | BO, HO | Тернопільська обл. | Ternopil | | BT, HT | Херсонська обл. | Kherson | | BX, HX | Хмельницька обл. | Khmelnytskyi | | CA, IA | Черкаська обл. | Cherkasy | | CB, IB | Чернігівська обл. | Chernihiv | | CE, IE | Чернівецька обл. | Chernivtsi | | CH, IH | м. Севастополь | Sevastopol |

Note the two easy-to-confuse pairs, verified against real registration data: CB = Chernihiv / CE = Chernivtsi (not the alphabetical order you'd guess), and AO = Zakarpattia / AT = Ivano-Frankivsk.

Development

npm install
npm run build
npm test

Related

License

MIT © trustcar.info