PhoneNumberKit: parsing and formatting international numbers in Swift
A Swift framework for parsing, formatting and validating international phone numbers. Inspired by Google's libphonenumber.
At a glance
- What is it?
- The marmelroy/PhoneNumberKit repository is frozen at 4.3.0 and points to a new organization. Here is what the Swift framework does, how to install the current package, and what the migration actually changes.
- Who is it for?
- Adopt PhoneNumberKit if you are building an iOS app that accepts international numbers and you want libphonenumber-derived metadata behind a Swift API. Do not adopt the marmelroy repository for new work: its README states it is frozen at 4.3.0 and no longer receives metadata updates, so validation data will drift.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 127 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What PhoneNumberKit solves, and who it is for
Phone numbers are not strings. A number typed by a user in Paris, Lagos or Sydney arrives with different spacing, an optional country prefix, and a trunk prefix that only makes sense inside one country. Turning that input into something you can store, dial or compare means deciding which country it belongs to, stripping the formatting, and checking that the result is a plausible number of the right type. PhoneNumberKit is a Swift framework that does exactly this: parse, format and validate international numbers, using metadata derived from Google's libPhoneNumber project. The README describes it as inspired by libphonenumber and credits its metadata to that project.
The audience is iOS and macOS developers writing Swift. The README lists automatic default region detection from the device, an AsYouType formatter for text fields, and conversion between country codes and country names. If your app only ever handles numbers from one country and you control the input format, the framework is more machinery than you need.
How parsing, validation and formatting actually work
Everything goes through a PhoneNumberUtility object. The README is explicit that allocating one is relatively expensive because it parses the metadata and keeps it in memory for the object's lifecycle, and it advises allocating once and releasing it when no longer needed. That is the central architectural fact: metadata loading is the cost, and parsing is cheap afterwards.
The parse call returns a PhoneNumber, an immutable Swift struct with properties for numberString, countryCode, nationalNumber, numberExtension and type (for example Mobile or Fixed). The region code is computed automatically from the device but can be overridden. By default the parser performs what the README calls hard type validation, which it also describes as quite costly performance-wise; passing ignoreType: true skips it. That is a real trade-off you have to make consciously: you can have type checking or speed, not both by default.
For bulk work there is an array parsing function. The README says invalid numbers are ignored in the resulting array, which means the output array can be shorter than the input and you lose the mapping between them unless you track it yourself. Formatting then converts a PhoneNumber into a string using a target type, with .e164, .international and .national shown in the README.
Installing the current package and parsing your first number
The marmelroy repository is frozen at 4.3.0. The README instructs readers to point their package at the PhoneNumberKit organization instead, at https://github.com/PhoneNumberKit/PhoneNumberKit, which covers version 5.0.0 and later. The module name PhoneNumberKit is unchanged, so the README states that core usage needs no source changes. Add the package through Swift Package Manager in Xcode or in your manifest, then import the module:
import PhoneNumberKitAll interactions go through a PhoneNumberUtility instance. Allocate it once, not per call:
let phoneNumberUtility = PhoneNumberUtility()Parsing returns a PhoneNumber or throws. The README gives this example, including a second call that overrides the region and skips type validation:
do {
let phoneNumber = try phoneNumberUtility.parse("+33 6 89 017383")
let phoneNumberCustomDefaultRegion = try phoneNumberUtility.parse("+44 20 7031 3000", withRegion: "GB", ignoreType: true)
}
catch {
print("Generic parser error")
}Once you hold a PhoneNumber, formatting is a single call with a target type. The README shows .e164, .international and .national, and the comments next to each line give the expected output shape:
phoneNumberUtility.format(phoneNumber, toType: .e164) // +61236618300
phoneNumberUtility.format(phoneNumber, toType: .international) // +61 2 3661 8300
phoneNumberUtility.format(phoneNumber, toType: .national) // (02) 3661 8300For batches, the array form takes a list of raw strings and a region, and silently drops entries it cannot validate:
let rawNumberArray = ["0291 12345678", "+49 291 12345678", "04134 1234", "09123 12345"]
let phoneNumbers = phoneNumberUtility.parse(rawNumberArray, withRegion: "DE", ignoreType: true)The AsYouType text field and the UI split
The README describes replacing a UITextField with PhoneNumberTextField to get the AsYouTypeFormatter, and notes that with Interface Builder the module field must be set to PhoneNumberKit. Two customization flags are documented: withFlag displays the country code for the currentRegion in the flagButton placed in the text field's leftView, and withExamplePlaceholder uses attributedPlaceholder to show an example number, with withPrefix inserting and removing the country prefix as editing changes.
The important detail for anyone migrating is that this UI layer no longer lives with the core. The README says PhoneNumberKitUI, at version 1.0.0 and later, holds PhoneNumberTextField and the country-code picker, and that users of those must add the PhoneNumberKitUI package and import PhoneNumberKitUI. Core parsing and formatting stayed in the main package. If your app never touches the text field, the migration is a dependency URL change. If it does, you are adding a package and an import.
The README also shows subclassing to force a region, overriding defaultRegion to return a fixed string such as "GB", and notes that PartialFormatter can be used directly, with PartialFormatter().formatPartial("+336895555") producing "+33 6 89 55 55".
Where PhoneNumberKit is the wrong tool
The clearest limitation is the one the README itself states: the marmelroy repository is frozen at 4.3.0 and no longer receives metadata updates, so its validation data will drift out of date over time. Phone number plans change. A library pinned to stale metadata will eventually reject numbers that are valid, or accept ones that are not. That is not a hypothetical risk, it is a documented property of this repository.
The second limitation is memory and lifetime. A PhoneNumberUtility parses metadata at allocation and holds it. Code that creates one per parse, or per table view cell, pays that cost repeatedly. The README warns about this directly, which suggests it is a common mistake.
The third is the array parser's silent filtering. Invalid entries are ignored, so a batch import can quietly lose rows. If you need to report which numbers failed, the array API does not give you that; you have to parse individually and catch errors.
Finally, the project is Swift and Apple-platform oriented. The README describes a framework built for iOS that grabs the default region from the phone. If you are writing server-side code in another language, or a Flutter or Android app, this is not the library for you.
PhoneNumberKit compared with libPhoneNumber-iOS
libPhoneNumber-iOS is the obvious alternative, and the difference is lineage rather than features. PhoneNumberKit's README states that it is inspired by Google's libphonenumber and that it uses metadata from Google's libPhoneNumber project, and it claims to be fully tested to match the accuracy of Google's JavaScript implementation. libPhoneNumber-iOS is the other well-known port of the same upstream metadata to Apple platforms.
So the real choice is about API shape and packaging, not about which project owns the numbering plan data. PhoneNumberKit exposes an idiomatic Swift surface: an immutable PhoneNumber struct, a PhoneNumberUtility object, an enum of format types, and a PartialFormatter for live editing. It is a Swift package with a podspec and Carthage compatibility noted in its badges. If your codebase is Swift-first and you want the AsYouType field, PhoneNumberKit reads more naturally. If you are maintaining an older Objective-C codebase, or you already depend on libPhoneNumber-iOS, switching buys you a different API over the same underlying data, which is rarely worth the churn on its own. The one thing that would justify a move is the metadata update path, and that now runs through the PhoneNumberKit organization rather than the marmelroy repository.
Maintenance, licence and the cost of staying on 4.x
The last push to the marmelroy repository was on 2026-05-25, the same day release 4.3.0 was published with the note "Deprecated; PhoneNumberKit has moved". The repository is not archived, but its README states plainly that it is no longer maintained and that active development lives in the PhoneNumberKit organization. Treat 4.3.0 as the final version here.
The upgrade path is documented. Point your package at https://github.com/PhoneNumberKit/PhoneNumberKit for 5.0.0 and later, and add PhoneNumberKitUI at 1.0.0 and later if you use the text field or picker. The README says the module name is unchanged and core usage needs no source changes, and it links a migration guide at MIGRATION.md in the new repository. That is the file to read before you bump the version, because the README summary only covers the core case.
The licence is MIT, which is permissive and places few conditions on redistribution; the LICENSE file is at the repository root. This is not legal advice, and if you vendor the metadata or ship a modified copy you should read the licence text and the upstream metadata terms yourself.
Editorial conclusion
Adopt PhoneNumberKit if you are building an iOS app that accepts international numbers and you want libphonenumber-derived metadata behind a Swift API. Do not adopt the marmelroy repository for new work: its README states it is frozen at 4.3.0 and no longer receives metadata updates, so validation data will drift. Verify two things before you commit: that your dependency points at the PhoneNumberKit organization package rather than the old URL, and whether you use PhoneNumberTextField or the country-code picker, because those moved into a separate PhoneNumberKitUI package and need an added import.
Frequently asked questions
Is PhoneNumberKit still maintained?
Not in the marmelroy repository. Its README states the repository is no longer maintained and is frozen at 4.3.0, and that active development moved to the PhoneNumberKit organization. The last push there was on 2026-05-25.
How do I migrate PhoneNumberKit to the new organization?
Point your package at https://github.com/PhoneNumberKit/PhoneNumberKit for version 5.0.0 and later. The README says the module name PhoneNumberKit is unchanged, so core usage needs no source changes, and a migration guide is linked at MIGRATION.md.
Does PhoneNumberKit work on Android or Flutter?
No. The README describes a Swift framework built for iOS that automatically grabs the default region code from the phone. There is no Android, Flutter or server-side implementation described in the repository.
Why does PhoneNumberKit ignore invalid numbers when parsing an array?
The README states that invalid numbers are ignored in the resulting array for the array parsing function. If you need to know which entries failed, parse them individually with the throwing parse call instead.
Does PhoneNumberKit need the PhoneNumberKitUI package?
Only if you use PhoneNumberTextField or the country-code picker. The README says those moved to PhoneNumberKitUI at 1.0.0 and later, and that you must add that package and import PhoneNumberKitUI. Core parsing and formatting stay in the main package.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/marmelroy-phonenumberkit)