A Swift library for parsing Machine Readable Zone (MRZ) content from travel documents, such as passports, that conform to formats defined in ICAO standard 9303. These are formats TD1, TD2, TD3, MRV-A, and MRV-B.
The library offers:
- Structured types representing data types in MRTDs (dates, names, etc)
- BAC password extraction if you need that
- Check digit validation
- "Long" document number support from TD1 and TD2, found in some national ID cards
- A utility library for parsing non-MRTD MRZs, if you really want/have to do that
- Reasonable speed, not awful
- Prevents you having to read ICAO 9303 yourself, hopefully
- It's very Sendable, if you enjoy concurrency
- No support for allowing incorrect check digits - it throws if they don't validate*. BUT it does understand ICAO 9303 logic for check digits on optional fields, so your Dutch service passport should parse
- Doesn't restrict secondary document codes for passports to the tighter list specified for docs issued 2026 onwards*
- Doesn't generate MRZs
- Doesn't do OCR, you want something else for that or use Vision
- Doesn't talk NFC, need something else for that too
- Does not include details from my own passport or from those of anyone I know, all test data are examples from ICAO or national/supranational MRTD issuers
* feel free to raise a PR if you hate these choices
Instantiate an MRTDParser with the output type you want to use.
import MRTDParser
let someMRZ = """
"""
let parser = MRTDParser<MRTDSummary>()
let summary = try parser.parse("...")
print(summary)If you aren't interested in parsing every possible element in the MRZ,
you can define your own type that conforms to MRTDMRZConvertible
and use it when you create an MRTDParser instance:
import MRZParsingUtilities
import MRTDParser
struct ExampleOutput: MRTDMRZConvertible {
let documentNumber: String
init(extractions: MRZExtractionCollection<MRTDElementLabel>) throws {
// populate your type's members here
let docNumberElementContent = try extractions.getExactlyOneOf(.documentNumber)
documentNumber = try String(mrzCharacters: docNumberElementContent)
}
}
let parser = MRTDParser<ExampleOutput>()
let sampleOutput = try parser.parse("....")
print(sampleOutput.documentNumber)MRTDBACPassword is an alternative output type that comes with the package and
only cares about the
You can parse non-ICAO formats by using MRZLayout from MRZParsingUtilities. See CustomMRZLayoutTests in MRZParsingUtilitiesTests for an example.
ICAO 9303 defines the MRZ format for conforming travel documents (and some visas): https://www.icao.int/publications/doc-series/doc-9303