Correctly validating phone numbers in Yup ensures you get clean user data. We'll walk through five different methods, providing working code for each. You'll also see the pitfalls of these traditional approaches and how Abstract API helps address them for more dependable results.
How to Implement Phone Number Validation in Yup
Here are four common ways to validate phone numbers with Yup. Each method has a different approach, from simple regular expressions to more complex, context-aware rules.
Regex with .matches
This method relies on a single regular expression and Yup’s built-in .matches function. You can keep the pattern close to the E.164 standard to avoid the need for country-specific rules. The code imports Yup and defines a schema for a string. It marks the field as required and then uses the .matches method with a regex pattern. The pattern checks for an optional plus sign, followed by a non-zero digit, and then 9 to 14 more digits.
import * as Yup from 'yup';
const phoneSchema = Yup.string()
.required('phone required')
.matches(/^\+?[1-9]\d{9,14}$/, 'invalid phone');
Custom .test with libphonenumber-js
This approach uses the libphonenumber-js library, which contains the same metadata Google uses for phone number validation. With Yup’s custom .test function, you delegate the complex logic to that library. This method handles both national and international formats.
The code imports `isValidPhoneNumber` from the library and Yup. It then defines a schema that uses .test, which receives the phone number value and passes it to isValidPhoneNumber to determine its validity.
import { isValidPhoneNumber } from 'libphonenumber-js';
import * as Yup from 'yup';
const phoneSchema = Yup.string().test(
'is-valid-e164',
'invalid phone',
value => isValidPhoneNumber(value || '')
);
External addMethod Plugin
Packages like yup-phone or yup-phone-lite extend Yup with a dedicated .phone() validator. These packages use Yup.addMethod behind the scenes to make the new validator available. They offer features like strict and loose validation modes and automatic country code defaults.
The code shows how to import Yup and the yup-phone package. You can then call .phone() directly on a string schema. The examples show how to set a default country, enforce strict validation, or provide a custom error message.
import * as Yup from 'yup';
import 'yup-phone'; // or 'yup-phone-lite'
const usSchema = Yup.string().phone().required(); // defaults to US
const inStrict = Yup.string().phone('IN', true).required();
const customError = Yup.string().phone('US', false, '${path} bad').required();
Context-aware .when Rules
You can use Yup’s .when method to bind the phone number validation rule to another field, such as a country selector. This allows you to switch validation patterns or plugins dynamically. This is useful for applications that need to handle multiple regions within a single code bundle.
The code defines an object schema with country and phone fields. The phone field’s validation depends on the country field. If the country is 'US', it applies a specific regex. Otherwise, it uses a different test function.
const schema = Yup.object({
country: Yup.string().required(),
phone: Yup.string().when('country', {
is: 'US',
then: Yup.string().matches(/^\+1\d{10}$/, 'US phone invalid'),
otherwise: Yup.string().test(
'intl',
'intl phone invalid',
v => isValidPhoneNumber(v || '')
)
})
});
Challenges of Phone Number Validation in Yup
While these methods offer a starting point, they introduce significant reliability and security issues. These drawbacks often lead to data integrity problems and create maintenance burdens for development teams.
- Numbering plans change often. Plugins like yup-phone depend on bundled metadata that can become outdated. This causes the validation to reject real numbers and accept fake ones, a problem for any library-based approach.
- The yup-phone plugin conflicts with Yup’s nullable contract. It flags empty values as errors, which forces developers to write extra .when or .test logic. This adds complexity and potential edge cases.
- Validation confirms only the format. Methods that use libphonenumber cannot verify if a number is active or reachable. A syntactically correct number might not receive an SMS, which requires external verification anyway.
- All checks execute in the browser. A user can disable JavaScript or modify the schema to bypass validation. Without server-side checks, your API trusts unvalidated data and exposes fraud vectors.
Validate Phone Numbers with Abstract API
Implement phone number validation in Yup to stop bad data and collect accurate user information.
Get started for free
How Abstract API Handles Phone Number Validation in Yup
Abstract API addresses the core weaknesses of traditional methods through real-time telecom data validation that moves beyond simple syntax checks.
- It moves past format checks to confirm if a number is live. The API returns a boolean “valid” flag from a real-time telecom dataset.
- The API provides rich metadata that includes the carrier, line type, and location. This information helps with fraud screens and improves SMS deliverability.
- It remains current with global number plan updates across more than 190 countries. This removes the need for constant data updates on the client side.
- The validation call moves the heavy work to the server. This prevents bloat in the client bundle and maintains a fast user experience.
How to Add Abstract API to Your Dev Environment
Once you understand Abstract’s capabilities, you can add its phone number validation API to your project with a few simple steps.
- Create a free account on Abstract API and get your Phone Validation API key.
- Install your preferred HTTP client, like Axios, in the project that already uses Yup.
- Place the key in a .env file and load it at startup.
- Call the validation function inside your form submit handler or server controller.
- Optionally, cache positive results and rate-limit calls to stay within your Abstract quota.
Sample Phone Number Validation with Abstract API
The helper function below first uses Yup for a quick format check on the client side. Then, it calls the Abstract API endpoint. The API performs a real-time check against telecom databases. If the number is not valid, the function throws an error. If it is valid, the function returns a JSON object with rich data about the number.
import axios from 'axios';
import * as Yup from 'yup';
const phoneSchema = Yup.string()
.required('phone required')
.matches(/^\+?[1-9]\d{9,14}$/, 'bad format');
export async function validatePhone(value) {
await phoneSchema.validate(value); // fast client check
const { data } = await axios.get(
'https://phonevalidation.abstractapi.com/v1/',
{ params: { api_key: process.env.ABSTRACT_API_KEY, phone: value } }
);
if (!data.valid) throw new Error('unreachable phone');
return data; // contains carrier, region, etc.
}
A successful validation returns a detailed JSON object. For example, a call with the number "14152007986" produces the following response:
{
"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."
}
Here, valid: true confirms the number is live. The format object provides normalized versions for your UI or database. The country, location, type, and carrier fields offer deeper context. You can use this data for regional logic or to block certain line types like VOIP.
Final Thoughts
Traditional validation only checks syntax. It cannot confirm if a number is active or identify its line type. This leaves gaps in fraud detection and SMS delivery. Abstract API closes these gaps with real-time data from over 190 countries. For more reliable phone validation, consider a free Abstract API account.
Validate Phone Numbers with Abstract API
Validate phone numbers in your Yup forms to maintain clean data and reliable user contact info.
Get started for free