German license plate parsing and validation. Framework-agnostic core with React adapter.
npm install kennzeichen- Parse German license plates with ambiguity detection
- 726 valid location codes (Unterscheidungszeichen)
- Handles E (electric) and H (historic) suffixes
- Framework-agnostic core
- React hook + headless component
import { LicensePlateInput } from "kennzeichen/react";
function MyInput({ value, onChange }) {
return (
<LicensePlateInput value={value} onChange={onChange}>
{({ inputProps, isOpen, options }) => (
<div>
<input {...inputProps} />
{isOpen &&
options?.map((opt) => (
<button key={opt.formatted} {...opt.getProps()}>
{opt.formatted}
</button>
))}
</div>
)}
</LicensePlateInput>
);
}import { useLicensePlate, formatParsedPlate } from "kennzeichen/react";
function LicensePlateInput({ value, onChange }) {
const { inputValue, handleChange, isDropdownOpen, options, selectOption } =
useLicensePlate({ value, onChange });
return (
<div>
<input value={inputValue} onChange={handleChange} />
{isDropdownOpen &&
options?.map((opt, i) => (
<button key={i} onClick={() => selectOption(opt)}>
{formatParsedPlate(opt)}
</button>
))}
</div>
);
}Use via CDN - no build step required:
<input type="text" id="plate-input" placeholder="Enter license plate...">
<div id="result"></div>
<script type="module" src="app.js"></script>// app.js
import { parseLicensePlate, formatParsedPlate } from
"https://cdn.jsdelivr.net/npm/kennzeichen/+esm"
const input = document.getElementById("plate-input")
const result = document.getElementById("result")
input.addEventListener("input", (e) => {
const parsed = parseLicensePlate(e.target.value)
if (parsed.type === "unambiguous") {
result.textContent = formatParsedPlate(parsed.plate)
} else if (parsed.type === "ambiguous") {
result.textContent = "Did you mean: " +
parsed.options.map(formatParsedPlate).join(" or ")
} else if (parsed.type === "invalid") {
result.textContent = "Invalid plate"
}
})import { parseLicensePlate } from "kennzeichen"
const result = parseLicensePlate("M-AB 1234")
if (result.type === "unambiguous") {
console.log(result.plate)
// { part1: "M", part2: "AB", part3: "1234" }
}
if (result.type === "ambiguous") {
// User needs to pick one
console.log(result.options)
}
if (result.type === "invalid") {
// Not a valid German license plate
}import { isValidLicensePlate } from "kennzeichen"
isValidLicensePlate("M-AB 1234") // true
isValidLicensePlate("XX-AB 1234") // false (invalid location)import { formatParsedPlate } from "kennzeichen"
formatParsedPlate({ part1: "M", part2: "AB", part3: "1234" })
// "M-AB 1234"Parses a license plate input string. Handles various formats: "M-AB 1234", "M AB 1234", "MAB1234".
Formats a parsed plate into standard display format: "M-AB 1234".
Returns true if the input is a valid, unambiguous German license plate.
Removes all spaces and hyphens from a license plate string.
Array of all 726 valid German location codes.
Render props component for license plate input.
Props:
value?: string- Controlled valueonChange?: (value: string) => void- Called when value changeschildren: (props: RenderProps) => ReactNode- Render function
RenderProps:
inputProps- Props to spread on input elementisOpen: boolean- Whether dropdown should be visibleoptions: OptionItem[] | null- Disambiguation options with helper methods
React hook for managing license plate input state.
Options:
value?: string- Controlled valueonChange?: (value: string) => void- Called when value changes
Returns:
inputValue: string- Current input valuehandleChange- Input onChange handlerisDropdownOpen: boolean- Whether dropdown should be visibleoptions: ParsedPlate[] | null- Disambiguation optionsselectOption(option)- Select a disambiguation option
type ParseResult =
| { type: "unambiguous"; plate: ParsedPlate }
| { type: "ambiguous"; options: ParsedPlate[] }
| { type: "partial"; plate: Partial<ParsedPlate> }
| { type: "invalid" }
type ParsedPlate = {
part1: string // Location code (e.g., 'M', 'HH', 'BGL')
part2: string // Letters (e.g., 'AB', 'X')
part3: string // Numbers + optional suffix (e.g., '1234', '99E', '42H')
}MIT