Free · Fast · Privacy-first

Regex for Phone Number Validation, Handle Every Format

Phone number formats vary enormously across countries, carriers, and individual user habits.

Test against international and local phone formats

🔒

Verify handling of spaces, hyphens, dots, and parentheses as separators

Check country code prefix handling with and without the + sign

Confirm extensions and vanity numbers are handled correctly

Cost
Free forever
Sign-up
Not required
Processing
In your browser
Privacy
Files stay local
FreeNo signupWhite-label

Add this Regex Tester to your website

Drop the Regex Tester into any page — blog post, product docs, intranet, school portal — with a single line of HTML. Your visitors get the full tool, processed entirely in their browser. No backend, no uploads, no signup.

  • Files stay 100% in the visitor's browser
  • Responsive — adapts to any container width
  • Free forever, no API key needed

Embed code

<iframe
  src="https://www.fixtools.io/developer/regex-tester?embed=1"
  width="100%"
  height="780"
  frameborder="0"
  style="border:0;border-radius:16px;max-width:900px;"
  title="Regex Tester by FixTools"
  loading="lazy"
  allow="clipboard-write"
></iframe>

Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.

Why Phone Number Validation Is Harder Than It Looks

Phone number validation is one of the most format-diverse problems in web development. A US number can appear as (555) 123-4567, 555-123-4567, 555.123.4567, 5551234567, or +1 555 123 4567, all representing the same underlying digits. UK numbers follow different length rules depending on whether they are geographic, mobile, freephone, or non-geographic service numbers. International numbers prefixed with the + E.164 sign can be followed by a country code of one to three digits and a national subscriber number of widely varying length. A regex that rigidly targets a single format will reject valid numbers from users who format their number according to their own regional convention, creating unnecessary friction at the point of highest intent in a form submission flow.

Phone validation regex must make a deliberate choice between strictness and permissiveness. The strictest useful approach is a country-specific pattern that enforces exact digit counts and validates known area code prefixes: for US numbers, ^(\+1\s?)?[2-9]\d{2}[\s.\-]?[2-9]\d{2}[\s.\-]?\d{4}$ enforces NANP rules and rejects invalid area codes starting with 0 or 1. The most permissive practical approach is a basic sanity check that verifies the field contains only plausible phone characters with a reasonable total length: ^\+?[\d\s.\-()]{7,20}$. Most applications benefit from the permissive approach paired with server-side normalisation: strip non-digit characters, verify the digit count falls in an expected range, and store the result in E.164 format for consistent downstream use.

For data pipelines that process phone fields from multiple sources with inconsistent formatting, the most reliable approach is to normalise first and validate second. Remove all non-digit characters except a leading plus sign, then verify that the resulting digit string falls within the expected length range. Seven to fifteen digits covers the international range set by the E.164 standard. For applications where country-specific validation is genuinely required because incorrect numbers cause measurable business problems such as failed SMS delivery or fraud, use a library like libphonenumber-js that encodes the national numbering plan rules for every country and handles edge cases that no general-purpose regex can reasonably cover.

Greedy versus lazy quantifier choice affects phone patterns more than developers expect. Consider extracting phone numbers from a paragraph of running text where numbers may be adjacent to ordinary digits or product codes. A greedy pattern \+?\d[\d\s.\-()]+ on the input "Call 555-1234 ext 99 or fax 555-5678" greedily consumes everything from the first digit through the run of separator-allowed characters, potentially merging two separate numbers into one match. The lazy variant \+?\d[\d\s.\-()]+? combined with a trailing word-boundary or length cap produces cleaner per-number extraction. For validation patterns anchored with ^ and $ this distinction matters less, because anchors force the engine to consider the whole string in one piece, but for extraction or scraping use cases the quantifier mood is the single most important knob to tune.

How to use this tool

💡

Paste your phone number validation regex and a list of phone numbers (one per line) in various formats. The tester shows which formats your pattern accepts and which it rejects.

How It Works

Step-by-step guide to regex for phone number validation, handle every format:

  1. 1

    Open the Regex Tester

    Navigate to the FixTools Regex Tester. The tool opens directly in your browser with no installation required. The pattern field, flag selector, and test string area are ready for input on a single page.

  2. 2

    Enter your phone regex

    Paste your phone number validation pattern into the pattern field. For a flexible starting point covering international formats, try ^\+?[\d\s.\-()]{7,20}$. For US-specific validation with NANP rules, try ^(\+?1[\s.\-]?)?\(?[2-9]\d{2}\)?[\s.\-]?[2-9]\d{2}[\s.\-]?\d{4}$.

  3. 3

    Enable g and m flags

    Set the global and multiline flags so all phone numbers in a multi-line test block are evaluated simultaneously. The global flag collects all matches, and the multiline flag ensures the anchors in your pattern evaluate independently against each line of the test string.

  4. 4

    Paste sample phone numbers

    Enter a list of phone numbers one per line, covering the full range of formats you expect from users. Include formats with parentheses around area codes, formats with hyphens, dots, and spaces as separators, numbers with and without country code prefixes, numbers with extension suffixes, and at least three obviously invalid strings to confirm they are rejected.

Real-world examples

Common situations where this approach makes a real difference:

Accepting US phone numbers in all common user-typed formats

A checkout form receives phone numbers typed as (555) 123-4567, 555-123-4567, 555.123.4567, and 5551234567 from different customers. The pattern ^(\+?1[\s.\-]?)?\(?[2-9]\d{2}\)?[\s.\-]?[2-9]\d{2}[\s.\-]?\d{4}$ is tested against all four format variants in the tester and all four produce match highlights. The developer also tests "123", "abcdefghij", and "00000000000" and confirms all three are correctly rejected before the pattern is deployed to the production form validation library.

Validating an international calling code prefix on a global booking platform

A travel booking site requires users to include a country code in E.164 format for SMS confirmation delivery. The pattern ^\+[1-9]\d{6,14}$ is tested against valid international numbers including +442071234567 and +15551234567. Testing also confirms that numbers submitted without the + prefix, numbers starting with +0, and bare local numbers without any country code are all correctly rejected, prompting the UI to show a clear error message asking the user to include their full international dialing code.

Cleaning a legacy CRM export that mixed phone formats

A data engineering team has a CSV export containing phone numbers stored as "(555) 123-4567", "555-123-4567 ext. 89", and "5551234567". A normalisation pattern strips all non-digit characters except a leading plus sign. After normalisation, a simple digit count validation \d{10,15} verifies the result falls within the expected range. Testing both the normalisation pattern and the digit-count validator in the tester against raw sample rows from the CSV confirms that the two-step approach correctly processes all three stored formats.

Rejecting obviously fake test numbers from a user database

An analytics team identifies that many test and bot accounts contain "1234567890" or "0000000000" as their phone number. Adding negative lookaheads to the validation pattern, such as ^(?!0{7,})(?!1234567890)\d{10}$, rejects these specific placeholder values at form submission time. The tester confirms that real phone numbers in the correct format still produce match highlights while both fake patterns and other repeated-digit sequences are correctly excluded.

When to use this guide

Use this page when you are building phone number validation for a form, API, or data cleaning pipeline and need to verify your pattern handles the formats your users submit.

Pro tips

Get better results with these expert suggestions:

1

Normalise before you validate, not after

Strip separators, parentheses, and spaces from the raw input before applying a strict digit-count validation pattern. This two-step approach handles every separator style a user might type without requiring the validation pattern to enumerate every separator combination explicitly. Test the stripping pattern first in the tester, then confirm the normalised output passes the digit-count validator, treating the two steps as independent and verifiable units.

2

Use digit count ranges rather than exact counts for international numbers

International phone numbers range from 7 digits for some Pacific island nations to 15 digits under the E.164 maximum. A pattern that enforces exactly 10 digits handles North American numbers but silently rejects valid numbers from the United Kingdom, Australia, France, and most other countries. Use \d{7,15} as the digit count constraint for any field that may receive international submissions and reserve exact counts for forms explicitly scoped to a single country.

3

Test with extension formats if your application collects them

Business phone fields regularly include extension suffixes: (555) 123-4567 x89 or +44 20 7123 4567 ext 456. Add an optional extension group to the end of your pattern such as (\s?(x|ext|extension)\.?\s?\d{1,6})?$ before the final anchor. Test both numbers that include an extension and numbers that do not to confirm the optional group handles both cases correctly without breaking the base number match.

4

Consider using libphonenumber for strict country-level validation

Regex alone cannot encode NANP area code validity rules, UK national numbering plan conventions, or Australian mobile prefix restrictions. For applications where phone number correctness is business-critical, such as SMS delivery services or identity verification workflows, integrate libphonenumber-js. Use regex only as a fast pre-screen to reject obviously non-numeric input before passing the candidate number to the library for authoritative country-level parsing.

FAQ

Frequently asked questions

A practical pattern that accepts the most common US phone number formats is ^(\+?1[\s.\-]?)?\(?[2-9]\d{2}\)?[\s.\-]?[2-9]\d{2}[\s.\-]?\d{4}$. This accepts (555) 123-4567, 555-123-4567, 555.123.4567, 5551234567, and +1 555 123 4567. It enforces NANP rules by requiring both the area code and the exchange code to start with a digit from 2 through 9, which prevents numbers starting with 0 or 1 in those positions that are not valid in the North American Numbering Plan.
Use ^\+[1-9]\d{6,14}$ to match E.164 formatted international numbers. This pattern requires a literal + prefix, a country code digit from 1 through 9 as the first digit after the plus, and a national subscriber number of 6 to 14 additional digits. The maximum of 15 total digits including the country code follows the E.164 standard. Test the pattern against sample numbers from several countries to verify that your minimum and maximum digit bounds cover the national numbering plan ranges you need to accept.
A general permissive pattern like ^\+?[\d\s.\-()]{7,20}$ accepts the most common phone number formats by allowing digits and the separator characters that users most frequently type. It does not validate country-specific digit count rules or area code conventions, but it reliably rejects strings that are clearly not phone numbers: pure alphabetic strings, strings shorter than 7 characters, and strings containing characters outside the permitted set. For stricter country-level validation, use a library like libphonenumber-js. The reason a single regex cannot honestly cover every country is that the global numbering plan defined in ITU-T E.164 allocates between 4 and 15 significant digits depending on the country code, with internal rules that vary by region: some countries reserve specific leading digits for mobile versus landline, some require a trunk prefix when dialled domestically but forbid it when dialled internationally, and some carve their numbering space into geographic blocks that change as new area codes are released. A regex that tried to encode all of this would need a per-country branch with alternation, would balloon past 10kB, and would still be wrong the next time a regulator opened a new prefix. A two-line wrapper around libphonenumber-js stays correct because Google ships the metadata updates as part of the package version, and your code only needs to bump the dependency to pick up new ranges. Use the regex to fail fast on garbage, then call the library for the authoritative answer.
Add an optional extension group at the end of your base pattern before the final anchor: (\s?(x|ext|extension)\.?\s?\d{1,6})?$. This matches extension notations written as x89, ext 456, and extension 1234 after the main number digits. The outer group is optional using ?, so numbers without an extension still match the base pattern. Test with a sample that includes numbers with and without extensions to confirm both cases produce correct results before deploying the pattern.
Country-specific digit counts vary widely. Enforcing exactly 10 digits works for North American numbers but rejects valid 7-digit numbers from smaller countries, 8-digit numbers from some European countries, and 11-digit mobile numbers from Russia and Brazil. Use a range like {7,15} for any field that may receive international input. If the form is explicitly scoped to a single country, check the national numbering plan for that country and set the exact expected digit range rather than using a North American assumption.
Use a replacement pattern to remove all non-digit characters except a leading plus sign. In JavaScript, phone.replace(/(?!^\+)[^\d]/g, '') preserves a + prefix if present and removes all other non-digit characters including parentheses, spaces, hyphens, and dots. Run the stripping pattern first to produce a normalised value, then validate the digit count of the result. Store the normalised value in E.164-like format for consistent database lookup and outbound formatting.
Use negative lookaheads to exclude specific repeated-digit sequences and sequential patterns: ^(?!0{7,})(?!1{7,})(?!1234567890)(?!9876543210)\d{10}$. This rejects strings like "0000000000", "1111111111", "1234567890", and "9876543210" that are the most common placeholder values used in test accounts and bot registrations, while accepting any real 10-digit number. Extend the lookahead list with additional fake patterns that are common in your specific user base.
Regex can verify that a string is shaped like a phone number, but it cannot tell you whether the area code is in service, whether the prefix is currently assigned to a real carrier, whether the number type is mobile or landline, or whether it can receive SMS messages. For any application where these distinctions matter (SMS-based identity verification, fraud screening, billing), use libphonenumber-js or the server-side Google libphonenumber. Treat the regex as a fast pre-screen that rejects clearly malformed input at form submission time, then defer to the library for authoritative parsing and number-type detection. This two-tier approach avoids loading a 200kB library for inputs that fail at the digit-count check.
The major flavours agree on the core mechanics needed for phone patterns: character classes, quantifiers, anchors, and grouping all work the same. The differences show up in two places. First, the named-group syntax: PCRE accepts both (?<name>...) and (?P<name>...), JavaScript accepts only (?<name>...), and Python's standard re module accepts only (?P<name>...). Second, Unicode handling of \d: in JavaScript and Python re, \d matches only ASCII digits 0-9 by default, while in .NET Regex and PCRE with the UCP flag, \d matches digits from every script including Arabic-Indic and Devanagari numerals. If your application accepts numbers typed in non-Arabic numerals, pin the digit class explicitly to [0-9] rather than relying on \d.

Related guides

More use-case guides for the same tool:

Ready to get started?

Open the full Regex Tester — free, no account needed, works on any device.

Open Regex Tester →

Free · No account needed · Works on any device