Are you excited to explorephone number validation in JavaScript?
Ensuring phone numbers is important in every aspect.
In this article, we’ll explain how to validate phone numbers straightforwardly using JavaScript and HTML.
Read on to learn the simplest method to validate phone numbers in JavaScript using Regular Expressions.
Validating phone numbers using regex in JavaScript
There are several ways to validate phone numbers using JavaScript. One common method is to use a regular expression (regex) to check if the input matches a specific pattern.
Below is the JavaScript Regex code you’ll need to validate phone numbers.
/^(?(\d{3}))?[- ]?(\d{3})[- ]?(\d{4})$/Let’s break this down to help you understand it more easily:
/^(?The number can begin with an open parenthesis.
(\d{3})For the format to be valid, you need to type three numbers. If there’s no parenthesis, those numbers should be at the beginning.
)?You can add a closing parenthesis with it.
[- ]?The string can have a hyphen if you want. You can put it after the parenthesis or after the first three digits. For example, you can write it as (143)- or 143-.
(\d{3})After that, you need to have three more digits in the number. It can be like this: (123)-456, 123-456, or 123456.
[- ]?You can add a hyphen at the end if you want, like this: (123)-456-, -123-, or 123456-.
(\d{4})$/Lastly, the series should finish with four numbers.
How to validate a phone number in JavaScript?
As we mentioned earlier you can validate phone number using regex in JavaScript.
Here’s an example of a function that uses a regex to validate phone numbers in the format (123) 456-7890, (123)456-7890, 123-456-7890, or 1234567890:
function validatePhoneNumber(input_str) {
var re = /^\\(?(\d{3})\\)?[- ]?(\d{3})[- ]?(\d{4})$/;
return re.test(input_str);
}
You can also use HTML5 form validation to validate phone numbers.
Here’s an example of an HTML form that uses the pattern attribute to specify a regex for validating phone numbers:
<form>
<label for="phone">Phone:</label>
<input type="tel" id="phone" name="phone" pattern="\\d{3}[ -]?\\d{3}[ -]?\\d{4}" required>
<input type="submit">
</form>
In our given example, the pattern attribute specifies a regex that checks for three digits, followed by an optional hyphen or space, three more digits, another optional hyphen or space, and finally four digits.
The required attribute specifies that the phone number field is required.
Here’s the complete example code:
<!DOCTYPE html>
<html>
<head>
<title>Phone Number Validation Form</title>
<h2>How to validate a phone number in JavaScript using Regex?</h2>
<script type="text/javascript">
function validatePhoneNumber() {
var phoneNumber = document.getElementById("phone").value;
var regex = /^\(?\d{3}\)?[- ]?\d{3}[- ]?\d{4}$/;
if (regex.test(phoneNumber)) {
alert("The phone number is valid.");
} else {
alert("The phone number is not valid.");
}
}
</script>
</head>
<body>
<form onsubmit="event.preventDefault(); validatePhoneNumber();">
<label for="phone">Phone:</label>
<input type="tel" id="phone" name="phone" required>
<input type="submit">
</form>
</body>
</html>
As you can see, we used the regular expression^(?\d{3})?[- ]?\d{3}[- ]?\d{4}$checks for an optional opening parenthesis, followed by three digits, an optional closing parenthesis, an optional hyphen or space, three more digits, another optional hyphen or space, and finally four digits.
Please note that this code will only work if JavaScript is enabled in the user’s browser. Also, this is a very basic form and does not include any server-side processing or error handling.
Output:
Here’s another example code using the regular expression ^(09|+639)\d{9}$ checks for exactly 11 digits. The phone number should start with 09 or +639.
<!DOCTYPE html>
<html>
<head>
<title>Phone Number Validation Form</title>
<h2>How to validate a phone number in JavaScript using Regex?</h2>
<script type="text/javascript">
function validatePhoneNumber() {
var phoneNumber = document.getElementById("phone").value;
var regex = /^(09|\+639)\d{9}$/;
if (regex.test(phoneNumber)) {
alert("The phone number is valid.");
} else {
alert("The phone number is not valid.");
}
}
</script>
</head>
<body>
<form onsubmit="event.preventDefault(); validatePhoneNumber();">
<label for="phone">Phone:</label>
<input type="tel" id="phone" name="phone" required>
<input type="submit">
</form>
</body>
</html>Output:
Different phone number regex patterns for 2026
Phone numbers come in many shapes. I always tell BSIT students working on their capstone forms: there is no single regex that catches every phone format on Earth. Instead, pick the pattern that matches your target users. Here are the three patterns I reach for most often.
1. Basic US phone number format
This one accepts numbers written as (123) 456-7890, 123-456-7890, or 1234567890. Good starter regex for a Philippine or American user base.
const phoneRegex = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
console.log(phoneRegex.test("(123) 456-7890")); // true
console.log(phoneRegex.test("123-456-7890")); // true
console.log(phoneRegex.test("1234567890")); // true
console.log(phoneRegex.test("12-34-567890")); // false2. International format with country code
If your form accepts users from multiple countries, you need a pattern that allows an optional plus sign, an optional country code, and flexible separators. This is the one I use for most capstone contact forms.
const intlPhoneRegex = /^\+?([0-9]{1,3})?[-. ]?\(?([0-9]{1,4})\)?[-. ]?([0-9]{1,4})[-. ]?([0-9]{1,9})$/;
console.log(intlPhoneRegex.test("+63 917 123 4567")); // true (Philippines)
console.log(intlPhoneRegex.test("+1-555-123-4567")); // true (US)
console.log(intlPhoneRegex.test("+44 20 7946 0958")); // true (UK)
console.log(intlPhoneRegex.test("917-123-4567")); // true (no country code)3. Strict E.164 format
E.164 is the international phone number standard used by SMS gateways, WhatsApp Business API, and Twilio. It looks like +639171234567 with no spaces or dashes, max 15 digits after the plus. Use this pattern when you plan to send SMS or integrate with a phone-based service.
const e164Regex = /^\+[1-9]\d{1,14}$/;
console.log(e164Regex.test("+639171234567")); // true
console.log(e164Regex.test("+15551234567")); // true
console.log(e164Regex.test("+0123456")); // false (starts with 0)
console.log(e164Regex.test("639171234567")); // false (missing +)How the phone number regex actually works
New JavaScript developers often copy a regex from Stack Overflow without knowing what each symbol does. That is a mistake. When your form starts rejecting valid phone numbers, you cannot fix what you cannot read. Here is the international pattern broken down piece by piece.
/^\+?([0-9]{1,3})?[-. ]?\(?([0-9]{1,4})\)?[-. ]?([0-9]{1,4})[-. ]?([0-9]{1,9})$/
^ Start of string (nothing before the phone number)
\+? Optional plus sign
([0-9]{1,3})? Optional country code, 1 to 3 digits
[-. ]? Optional separator: dash, dot, or space
\(? Optional opening parenthesis
([0-9]{1,4}) 1 to 4 digits (area code)
\)? Optional closing parenthesis
[-. ]? Optional separator
([0-9]{1,4}) 1 to 4 digits (first block)
[-. ]? Optional separator
([0-9]{1,9}) 1 to 9 digits (final block)
$ End of stringThe ^ and $ anchors are critical. Without them, the regex would match a valid phone number embedded inside garbage input like “call me at 123-456-7890 haha”, which is not what you want in a form validator.
Real-world example: HTML form with phone number validation
Here is a complete working example. The form accepts a phone number, validates it on submit, and shows an inline error message if the input is wrong. I use this exact pattern in my capstone project templates for BSIT students building contact forms and user registration pages.
<form id="contactForm">
<label for="phone">Phone Number</label>
<input type="tel" id="phone" name="phone" required>
<span id="phoneError" style="color:red;display:none;">
Please enter a valid phone number.
</span>
<button type="submit">Submit</button>
</form>
<script>
document.getElementById("contactForm").addEventListener("submit", function(e) {
e.preventDefault();
const phoneInput = document.getElementById("phone");
const errorEl = document.getElementById("phoneError");
const phoneRegex = /^\+?([0-9]{1,3})?[-. ]?\(?([0-9]{1,4})\)?[-. ]?([0-9]{1,4})[-. ]?([0-9]{1,9})$/;
if (!phoneRegex.test(phoneInput.value)) {
errorEl.style.display = "inline";
phoneInput.focus();
return false;
}
errorEl.style.display = "none";
console.log("Phone number is valid:", phoneInput.value);
// Continue with form submission logic
});
</script>Notice I used type="tel" on the input. This tells mobile browsers to show the numeric keypad, which improves usability on phones. The HTML5 validation alone is not enough because it accepts almost anything as valid, so we still need the regex check in JavaScript.
Common phone number regex mistakes to avoid
I have reviewed hundreds of capstone forms over the years. These are the five phone validation mistakes I see most often. Fix these and your form will handle real-world phone numbers correctly.
- Forgetting the anchors. Without
^and$, your regex matches partial phone numbers inside garbage text. Every phone validator should be anchored. - Hardcoding only one country format. If your regex accepts only (XXX) XXX-XXXX, users from the Philippines with numbers like 09171234567 get rejected. Support at least the international pattern.
- Treating regex as the only defense. Regex checks format but not authenticity. For real SMS-based verification, send a one-time code to the number. Regex is your first filter, not your last check.
- Not escaping special characters. The plus sign and parentheses in regex have meaning. If you forget the backslash on
\+,\(, or\), the pattern will not match what you expect. - Rejecting valid formats due to spacing. Users type phone numbers with dashes, dots, spaces, or nothing at all. Your regex should accept all reasonable separators using
[-. ]?, not force a single format.
By the way, if you are handling a lot of international phone numbers, consider using Google’s libphonenumber library instead of pure regex. Regex validates format, but libphonenumber validates real number ranges, country codes, and carrier prefixes. For a simple contact form, pure regex is enough. For a production app that sends SMS or verifies users, use the library.
Official documentation
- MDN Regular Expressions Guide covers the full JavaScript regex syntax.
- MDN RegExp.prototype.test() is the reference for the test() method used in this tutorial.
- Google libphonenumber is the production library for international phone validation.
Conclusion
In conclusion, this article has exploredhow to validate phone numbers in JavaScript using Regular Expressions (regex).
We’ve covered the essential regex patterns for validating various phone number formats, explained the code breakdown, and offered practical examples for implementing phone number validation in both JavaScript functions and HTML forms.
It’s important to remember that the code examples provided here are basic and serve as a starting point for implementing phone number validation in your web applications.
We hope this article has provided you with enough information to understand phone number validation in JavaScript and implement it effectively in your projects.
If you want to explore more JavaScript topics, check out the following articles:
Thank you for reading Itsourcecoders .
Quick step-by-step summary (click to expand)
- Choose the phone format. Decide US-only or international E.164 based on your audience.
- Write the regex. Use /^\+[1-9]\d{1,14}$/ for E.164 or a US-only pattern for domestic forms.
- Test with .test(). Run the regex against real sample numbers before shipping.
- Wire to your form. Attach onChange or onBlur handlers that show errors in real time.
- Repeat on the server. Never trust client-side alone. Validate again in your backend.
International phone validation with the E.164 standard
If your form accepts users outside one country, a US-only pattern breaks the moment someone enters a UK, India, or Philippines number. The E.164 international phone standard gives you a canonical format for every country: a leading plus, a country code, and up to 15 digits total.
The minimum viable E.164 regex looks like this:
const e164 = /^\+[1-9]\d{{1,14}}$/;
e164.test("+639171234567"); // true (Philippines)
e164.test("+14155552671"); // true (US)
e164.test("+919876543210"); // true (India)
e164.test("+447700900123"); // true (UK)
e164.test("09171234567"); // false (missing + and country code)
e164.test("+0123456789"); // false (E.164 disallows leading 0 after +)This pattern intentionally accepts any length from 2 to 15 digits after the plus, which matches the E.164 spec. What it does NOT do is verify the country code is real, or that the number is assigned. For that, you need a data-driven library. The most reliable one is Google’s libphonenumber, ported to JavaScript as libphonenumber-js on npm.
import {{ parsePhoneNumberFromString }} from 'libphonenumber-js';
const phone = parsePhoneNumberFromString('09171234567', 'PH');
if (phone && phone.isValid()) {{
console.log(phone.number); // +639171234567
console.log(phone.country); // PH
console.log(phone.formatInternational()); // +63 917 123 4567
}}Use plain regex for lightweight forms that only need a shape check. Use libphonenumber when a wrong number costs you money (OTP SMS, delivery notifications, appointment reminders).
Modern JavaScript approaches in 2026 (beyond raw regex)
Regex is still the fastest way to validate phone shape, but 2026 browsers give you two more layers that catch mistakes earlier and improve accessibility. Use them together with your regex, not instead of it.
The <input type="tel"> element
Every modern browser recognizes type=”tel” and pops a phone-optimized keypad on mobile. It does not validate the value (any string is accepted), but it gets the user typing digits instead of letters in the first place, which cuts a whole class of errors before your regex runs.
<input
type="tel"
id="phone"
name="phone"
autocomplete="tel"
inputmode="tel"
pattern="^\+?[0-9\s\-\(\)]{{7,20}}$"
required
placeholder="+63 917 123 4567"
/>The pattern attribute runs the regex on form submit for free, and the autocomplete="tel" attribute lets browsers autofill from the user’s saved profile. On iOS Safari and Chrome Android, this combination alone raises phone-form completion rates by 15 to 25 percent.
The Constraint Validation API
Once the pattern attribute is set, JavaScript can query validity without re-parsing the string:
const input = document.getElementById('phone');
input.addEventListener('blur', () => {{
if (!input.validity.valid) {{
if (input.validity.patternMismatch) {{
input.setCustomValidity('Enter a phone number like +63 917 123 4567');
}} else if (input.validity.valueMissing) {{
input.setCustomValidity('Phone number is required');
}}
}} else {{
input.setCustomValidity('');
}}
}});This is faster than a custom regex check because the browser already validated the pattern; you are just reading the result. It also plays nicely with screen readers, which announce setCustomValidity messages to visually impaired users.
The Intl API for formatting
Once a phone number is validated, use the Intl namespace to display it in the user’s regional format. There is no built-in Intl.PhoneNumberFormat yet (it is under discussion in TC39), but libphonenumber-js exposes the same formatting through formatNational() and formatInternational(). Standardize the storage format (always E.164) and defer the display format to the render layer.
Framework integration and testing patterns
A phone validator is nothing without tests. And in a modern React, Vue, or Node.js codebase, your regex sits behind a component or a helper function, not in a raw form. Here are the patterns that ship in production apps.
React controlled input
import {{ useState }} from 'react';
const phoneRegex = /^\+[1-9]\d{{1,14}}$/;
export function PhoneField() {{
const [phone, setPhone] = useState('');
const [error, setError] = useState('');
const handleChange = (e) => {{
const value = e.target.value;
setPhone(value);
if (value && !phoneRegex.test(value)) {{
setError('Enter international format, e.g. +639171234567');
}} else {{
setError('');
}}
}};
return (
<div>
<input
type="tel"
value={{phone}}
onChange={{handleChange}}
autoComplete="tel"
placeholder="+639171234567"
/>
{{error && <span style={{{{ color: '#c00' }}}}>{{error}}</span>}}
</div>
);
}}Validating on every keystroke can feel jumpy. Debounce the check with useEffect and a 300ms timer if your users complain, or validate only on onBlur for a calmer feel.
Testing your regex with Jest or Vitest
Regex bugs slip past manual testing because you rarely try every edge. A table-driven test covers the whole surface in one file. This works in both Jest and Vitest:
import {{ describe, test, expect }} from 'vitest';
const phoneRegex = /^\+[1-9]\d{{1,14}}$/;
const cases = [
{{ input: '+639171234567', valid: true, note: 'PH mobile' }},
{{ input: '+14155552671', valid: true, note: 'US number' }},
{{ input: '+919876543210', valid: true, note: 'India mobile' }},
{{ input: '+447700900123', valid: true, note: 'UK mobile' }},
{{ input: '09171234567', valid: false, note: 'missing country code' }},
{{ input: '+0123456789', valid: false, note: 'leading 0 after +' }},
{{ input: '+63', valid: false, note: 'too short' }},
{{ input: '+123456789012345678', valid: false, note: 'too long' }},
{{ input: 'abc', valid: false, note: 'letters' }},
{{ input: '', valid: false, note: 'empty' }},
];
describe('phone regex E.164', () => {{
cases.forEach(({{ input, valid, note }}) => {{
test(`${{note}}: ${{input || 'empty'}}`, () => {{
expect(phoneRegex.test(input)).toBe(valid);
}});
}});
}});Every time you touch the regex, run this file. If a test flips from pass to fail, you know exactly which case regressed. This is 10 minutes of setup that saves hours of production debugging when the marketing team suddenly asks for South American number support.
Node.js server-side validation
Never trust the client. Even with a strict client-side regex, a determined user can bypass the input by submitting the form directly with cURL or Postman. Repeat the validation on the server:
// Express route
app.post('/api/signup', (req, res) => {{
const {{ phone }} = req.body;
const phoneRegex = /^\+[1-9]\d{{1,14}}$/;
if (!phone || !phoneRegex.test(phone)) {{
return res.status(400).json({{ error: 'Invalid phone format' }});
}}
// proceed with save
}});For high-stakes flows (payment, KYC, OTP), also run libphonenumber-js server-side and reject numbers where isValid() returns false. This catches typo-prone country codes that pass the shape regex but do not correspond to any real country prefix.
Frequently Asked Questions
What is the simplest regex for validating phone numbers in JavaScript?
How do I validate Philippine mobile phone numbers (09xx) in JavaScript?
What is the difference between using a JavaScript regex and the HTML5 pattern attribute?
Why is my phone regex matching invalid numbers?
How do I allow the + country code prefix in the regex?
Should I use libphonenumber instead of a regex for phone validation?
What is E.164 international phone number format?
How do I show a custom error message when phone validation fails?
Can I validate a phone number on input change instead of on submit?
Does the regex pattern work the same in Node.js and the browser?
We are hoping that this article helps you validate phone numbers in JavaScript more confidently. If you have any questions or suggestions about phone number regex in JavaScript, please feel free to drop them in the comments below or contact us at our contact page.
