Skip to content

🔍 Phone Number Regex Builder (30+ Countries)

Instantly generate validation regex for phone numbers across 30+ countries. Four variants (E.164 / International / Flexible / Mobile-only), multi-country OR combination, live tester and ready-to-paste snippets for JavaScript, PHP, Python, Ruby and Go. Perfect for form validation, log extraction and data cleansing.

100% Free No signup Browser-only 5 languages Dark mode

🔒 About Privacy

📝 Generated regex

/^.+$/g

🧪 Live tester

0 matched
    0 unmatched

      💻 Code snippets per language

      
          

      📖 Where people get stuck

      Generates phone number validation patterns for more than thirty countries, in four variants (E.164, international, lenient and mobile-only), with OR-combination across countries, a live tester and snippets for JavaScript, PHP, Python, Ruby and Go. Everything runs in the browser. What a regular expression can decide, however, is only whether the shape looks like a numberit cannot tell you whether that number exists, is still in service, or can receive an SMS. And numbering plans change: allocate a new leading digit and a pattern that was correct yesterday starts rejecting real numbers today.

      Case What happens What to do
      An over-strict pattern rejects real numbers Numbering schemes are managed by each country regulator and change every few yearsnew leading digits are added for mobile, area codes are split, ranges are created for new services. A pattern that enumerates leading digits in detail is accurate at the moment it is written and gradually begins to reject real numbers. And because of number portability, the inference that a given prefix means mobile and therefore SMS-capable no longer holdsthe mapping from range to carrier is not fixed. Meanwhile the rejected user leaves without knowing whysomeone holding a perfectly valid number who is told it is invalid has no move available to them. Use the pattern only to reject input that is obviously wrong. Concretely, keep it to a minimum and maximum length, the permitted character set, and a plausible country codeenumerating the first three digits is safer left unwritten unless you are prepared to keep maintaining it. Where correctness matters — SMS verification, identity checks, billing — use a maintained library: libphonenumber tracks national numbering plans continuously, and there is no reason to take that work on yourself. The only way to establish that a number is actually reachable is to send to itand once you send a verification code by SMS, the precision of your regular expression stops mattering to the final result.
      Validating before normalizing People write the same number in many different wayswith and without hyphens, separated by spaces, in parentheses, with and without the country code, with and without a leading zero, and in full-width digits. Copy from a smartphone contact list and invisible control characters and unusual spaces can come along too. Feed the raw string to a pattern and all of these come out invalidand the person who typed it cannot see what is different (full-width and half-width digits differ only in width in many fonts). The other awkward case is the leading zero in national versus international formatin many countries a number carries a leading 0 domestically and drops it when the country code is prefixed. If you want to accept both, you have no choice but to convert to one form before comparing. Fix the order as normalize, validate, store. To normalize: convert full-width to half-width (see the width converter) and strip everything except digits and a leading +that alone absorbs most of the variation listed above. Validate against the normalized string, and store in E.164 form, meaning + followed by the country code and digits onlyin that form, comparison, duplicate detection and international sending all work directly. Format it to local convention only when displaying it. And allow hyphens and spaces in the input fieldtelling the user to enter digits only is just pushing the normalization work onto them.
      The pattern behaves differently in each engine The tester here runs on the JavaScript engine, so a pattern that passes there does not necessarily behave the same where you paste it. Three differences stand out. The Go regexp package is RE2, so lookahead ((?=...)) and backreferences are unavailablea pattern containing them fails at compile time. PHP preg_match requires delimiters; without wrapping in /.../ it warns and matches nothing. Anchors vary too$ in many engines also matches just before a trailing newline, so an input like a number followed by a newline and further text can slip through (in JavaScript and Python you need \z or \Z, or to strip newlines first). Always run the generated pattern once in the language you will actually use. Go in particular does not misbehave, it fails at startup, so without a test you find out in production. Prepare three kinds of test case: valid numbers that must pass, obviously wrong input that must be rejected, and boundaries — shortest, longest, with and without country code. Including the input that must be rejected is the crucial parttest only the happy path and a broken pattern that accepts everything still shows green. And do not inline the pattern in your code: give it a name and keep it in one placeso that when the numbering plan changes, there is a single place to fix.

      How strict to be follows from what the number is for. On an optional field in a contact form, strict validation only reduces the number of enquiriesif you cannot be reached, the person who loses out is the one who typed it, and you do not need to adjudicate on their behalf. Conversely, for SMS verification or a delivery contact, failing to send is an immediate operational failure, so put actual reachability, meaning sending a verification code, into the process rather than relying on format validation. Treating those two cases with the same strictness is the most common design mistake. Also, a phone number is personal datado not print it to logs, do not include it in error messages, and do not pass it to analytics as a URL parameter. Designs that send the in-progress value to a validation API in real time deserve particular care. And avoid displaying only the word invalidstate how many digits are expected and whether the country code is needed, and show an example; most input mistakes resolve themselves on the spot.

      📖 How to Use

      1. 1
        Pick target countries
        Pick a single country or several to combine into one OR pattern (perfect for international forms). 30+ countries supported.
      2. 2
        Choose a variant
        Pick from E.164 (strict + country-code), International (with separators), Flexible (intl + national) or Mobile-only.
      3. 3
        Copy or test
        Copy the regex with one click. Paste a list of numbers into the live tester to see matches and failures in real time.
      4. 4
        Paste into your language
        Ready-to-run snippets for JavaScript, PHP, Python, Ruby, Go and Java are generated automatically with proper escaping.

      ❓ Frequently Asked Questions

      Why not use libphonenumber?
      libphonenumber-js is around 70 KB which is overkill if you just want a small regex for form validation. We hand-write rules for 30+ common countries so you can copy-paste with zero dependencies. For full accuracy use libphonenumber.
      What is the difference between International and E.164?
      E.164 is the ITU-T standard (e.g. +819012345678) — pure digits, max 15, no spaces or punctuation. International format is the human-readable variant with spaces and hyphens (+81 90-1234-5678). Convention: store as E.164, display as International.
      Can I combine multiple countries into one regex?
      Yes. Tick multiple countries and the tool emits a single OR (|) pattern combining all of them — perfect for global form validation or extracting numbers from mixed logs.
      Is the generated regex perfect?
      It is a practical approximation aimed at ~80% validity. Numbering plans drift across carriers and years, so for bank-grade or telco-grade validation use libphonenumber or each national telecom regulator. For form inputs and log extraction these patterns are plenty.

      🔗 Related Tools

      🐛 Found a bug or issue with this tool?

      Free to use, no signup. Even just the steps to reproduce are helpful. Reports go directly to the operator and help us fix issues.

      * Browser info (UA / screen / language / URL) is sent automatically to help reproduce the issue