Validating phone numbers is a frequent requirement in Java applications to maintain data integrity. We will look at four ways to implement this validation, complete with working code snippets, then discuss the pitfalls of common methods and how Abstract API effectively solves them.
How to Implement Phone Number Validation in Java
Phone number validation in Java can be approached with a few distinct techniques. These methods cover different levels of correctness and provide various operational guarantees for your application.
Regular Expressions with java.util.regex.Pattern
The use of regular expressions, or regex, offers a direct solution. A regex pattern defines a search pattern for strings. For phone validation, you create a pattern that matches valid number formats.
The `java.util.regex.Pattern` class compiles this pattern. For efficiency, you should compile the pattern once when the application starts and reuse the compiled object for all subsequent validations.
The code below defines two patterns. The first checks for the ITU E.164 standard, and the second handles the common North American 10-digit format. The `isValid` method returns true if the input string matches either pattern. More elaborate expressions are also possible.
private static final Pattern E164 =
Pattern.compile("^\\+\\d{1,3}\\s?\\d{1,14}$"); // ITU E-164
private static final Pattern US_LOCAL =
Pattern.compile("^(\\+1\\s?)?((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$");
boolean isValid(String raw) {
return E164.matcher(raw).matches() || US_LOCAL.matcher(raw).matches();
}
Google's libphonenumber Library
Google's `libphonenumber` is a comprehensive library for phone number manipulation. It includes metadata for nearly every telephone numbering plan on the planet, which allows for semantic validation.
This goes beyond simple checks for length or prefixes. To use it, you first add the library as a dependency in your project, for example, with Maven.
The validation logic involves several steps. First, you parse the number string with a region hint, like "US". Then, you can use different methods for checks. The `isPossibleNumber` method checks length and format, while `isValidNumber` enforces region-specific rules, like reserved prefixes. The library can also format the number into a standard format like E.164.
<!-- Maven -->
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>libphonenumber</artifactId>
<version>8.13.34</version>
</dependency>
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
Phonenumber.PhoneNumber num = util.parse(raw, "US"); // region hint
boolean syntaxOk = util.isPossibleNumber(num); // length/format
boolean valid = util.isValidNumber(num); // national rules
String e164 = util.format(num, PhoneNumberUtil.PhoneNumberFormat.E164);
Jakarta Bean Validation Custom Constraint
If your project already uses a Jakarta EE stack, such as Hibernate Validator, you can create a custom constraint. This approach wraps a validation strategy, like `libphonenumber`, inside a reusable annotation.
You define a custom annotation, such as `@Phone`. Then, you create a validator class that implements the `ConstraintValidator` interface. This class contains the actual logic to check the phone number's validity.
In the example, the `PhoneValidator` uses Google's `libphonenumber` to perform the check. Once defined, you can annotate fields in your DTOs or entities with `@Phone`. The validation layer then automatically blocks invalid data before it reaches your business logic.
@Target({ FIELD, PARAMETER })
@Retention(RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone { String message() default "invalid phone"; }
public final class PhoneValidator implements ConstraintValidator<Phone,String> {
private static final PhoneNumberUtil UTIL = PhoneNumberUtil.getInstance();
public boolean isValid(String raw, ConstraintValidatorContext ctx) {
try {
return UTIL.isValidNumber(UTIL.parse(raw, "US"));
} catch (NumberParseException e) { return false; }
}
}
Challenges of Phone Number Validation
While methods like regular expressions and libphonenumber
offer initial solutions, they come with significant drawbacks. These pitfalls can compromise the accuracy and reliability of your validation logic.
- International number plans have complex rules with variable lengths and prefixes. A single regex pattern often fails to cover all global cases, which leads to incorrect validation for users outside a specific region.
- Numbering plans change constantly with new area codes. Libraries like
libphonenumber
depend on metadata that can become outdated, so the validation logic may reject new, valid numbers or accept old, invalid ones. - Both regex and
libphonenumber
only confirm a number's format, not its actual existence or reachability. This creates a false sense of security, as the validation cannot tell if a number is truly active or assigned. - The
isPossibleNumber
check in libphonenumber
uses broad heuristics. For example, it allows a wide range of digit lengths for a country, so obviously incorrect numbers can still pass initial format checks.
Validate Phone Numbers with Abstract API
Ensure your user data is accurate by implementing phone number validation in your Java application.
Get started for free
How Abstract API Handles Phone Number Validation in Java
Abstract API addresses the core weaknesses of traditional validation methods. It uses a centralized REST API backed by live data to deliver accurate, real-time results.
- Regex-only checks often fail to detect carrier changes or number reuse. The API consults a continuously updated data set and returns a simple boolean 'valid' flag based on live numbering-plan intelligence.
- Locale libraries force developers to ship new releases for every numbering-plan update. Abstract centralizes this logic, so your service inherits fresh data without a new deploy.
- Self-maintained carrier and line-type detection is difficult. Abstract returns the carrier name, line type, and geographic hints automatically.
- Open libraries possess uneven global coverage. Abstract supports more than 190 countries and normalizes every response for consistency.
- Code-only solutions lack per-request audit trails. The rate-limited SaaS model secures usage, logs requests by key, and offloads compliance tasks.
How to Bring Abstract API to Your Dev Environment
Once you are familiar with Abstract’s capabilities, the addition of its phone number validation API to your project is simple.
- First, sign up at Abstract API and copy your Phone Validation API key.
- Next, add an HTTP client dependency. You can use the built-in java.net.http for JDK 11+ or another like OkHttp.
- Create a constant for the base URL: https://phonevalidation.abstractapi.com/v1/.
- Then, build the request URL with your key and the target phone number.
- Execute a GET request to the API and capture the JSON response.
- Finally, map the JSON to a Java object for use in your application.
Sample Phone Number Validation Implementation with Abstract API
The Java code below sends a GET request to the API endpoint. It includes your unique API key and the phone number you want to validate. The API returns a JSON object, which the code then maps to a `PhoneValidationResult` class so you can easily access the data in your application.
HttpClient client = HttpClient.newHttpClient();
String url = "https://phonevalidation.abstractapi.com/v1/?api_key=" + apiKey + "&phone=" + phone;
HttpRequest req = HttpRequest.newBuilder(URI.create(url)).GET().build();
HttpResponse<String> res = client.send(req, BodyHandlers.ofString());
PhoneValidationResult result = new ObjectMapper().readValue(res.body(), PhoneValidationResult.class);
if (result.isValid()) { … }
A successful request returns a detailed JSON response like this:
{
"phone": "14152007986",
"valid": true,
"format": {
"international": "+14152007986",
"local": "(415) 200-7986"
},
"country": {
"code": "US",
"name": "United States",
"prefix": "+1"
},
"location": "California",
"type": "mobile",
"carrier": "T-Mobile USA, Inc."
}
This single API call provides multiple data points that would otherwise require several libraries and carrier feeds.
- The valid flag confirms the number exists and is currently routable.
- The format object gives you ready-to-display international and national strings.
- The country and location fields support geo-based feature toggles or fraud rules.
- The type and carrier details allow you to push SMS traffic only to mobile devices or block risky premium lines.
Final Thoughts
Traditional validation methods depend on brittle pattern checks and local libraries that quickly become outdated. This approach fails to detect reused numbers or carrier changes. Abstract API solves these problems with a centralized service that consults live data for every request. To reliably validate user phone numbers, create a free account and get your API key.
Validate Phone Numbers with Abstract API
Add phone number validation to your Java application to ensure data integrity and connect with users.
Get started for free