Blog / Coding tips

UK Phone Number Regex for JavaScript and Python (Tested)

Cover image for UK Phone Number Regex for JavaScript and Python (Tested)

The most reliable UK phone number regex is a short one applied to a cleaned-up number. First normalise what the user typed: remove spaces, hyphens, dots and brackets, drop a (0), and turn a leading +44, 0044 or 44 into 0. Then a UK mobile is /^07\d{9}$/ (07 followed by nine more digits, 11 digits in all), and a stricter version that leaves out 070 personal numbers and 076 pagers is /^07(?:[1-57-9]\d{8}|624\d{6})$/. Any UK number, landline or mobile, is /^0(?:1\d{8,9}|[2357]\d{9}|8\d{8,9}|9\d{9})$/. Store the result in international E.164 form (+447700900123) and format it with spaces only for display. A regex checks the shape of a number, not whether it's in use. If that matters, use libphonenumber, as covered further down.

Trying to do all of that with one regex on the raw input is why so many patterns online are long and still reject real numbers. Below is a small, tested set of helpers for JavaScript and Python, a comparison with the popular one-line regex, results from Google's libphonenumber in both languages, and a browser gotcha with the HTML pattern attribute that silently turns validation off. Every test number comes from the ranges Ofcom reserves for TV and radio drama, plus the libraries' own example numbers, so none of them belongs to a real person. Everything was run on 6 October 2026 with Node 20.19, Python 3.13.5 and headless Chrome 154.

How UK phone numbers are structured

Before writing a pattern, it helps to know what you're matching. In national format (starting with 0), a UK number is 10 or 11 digits long, and the first two digits tell you what kind of number it is:

  • 01 and 02: geographic landlines. 020 is London, 0113 is Leeds, 0161 is Manchester, and so on. Most are 11 digits; a few smaller areas still use 10.
  • 03: UK-wide numbers charged like a landline call, popular with councils, the NHS and charities.
  • 05: corporate and internet-phone (VoIP) numbers.
  • 07: mobiles. Almost all 07 numbers are mobiles, with two exceptions: 070 is "personal numbering" (a redirect service often used in scams) and 076 is pagers, apart from 07624, which is used for Isle of Man mobiles.
  • 08: freephone (0800, 0808) and special-rate services.
  • 09: premium rate.
  • 00 and 06: not used for normal UK numbers. 00 starts an international call, and 06 isn't allocated.

In international format, you drop the leading 0 and add the UK country code, +44. So 07700 900123 becomes +44 7700 900123, and written without spaces, +447700900123. That compact form is called E.164, and it's what SMS services, phone systems and most databases expect. You'll also see 0044 in place of + (the international dialling prefix from a UK phone) and, in email signatures, +44 (0)7700 900123. The (0) is common but strictly incorrect, because you shouldn't dial the 0 after +44.

Ofcom publishes ranges set aside for fiction, which makes them perfect test data: mobiles 07700 900000 to 900999, London 020 7946 0000 to 0999, Leeds 0113 496 0000 to 0999, and others for freephone, premium and UK-wide numbers. The full list is on Ofcom's page of telephone numbers for use in TV and radio drama. Use these in your tests, documentation and screenshots rather than making numbers up, because a made-up number might belong to someone.

Normalise first, then match: JavaScript

Here's the module. It's split into three steps so each one is easy to read and test on its own:

// uk-phone.mjs: normalise, validate and format UK phone numbers (no libraries)

// 1. Turn whatever the user typed into national digits: "07700900123"
export function normaliseUkPhone(input) {
  let s = String(input).trim();
  s = s.replace(/\(0\)/g, "");          // "+44 (0)20 ..." -> drop the (0)
  s = s.replace(/[\s\-().]/g, "");      // spaces, hyphens, brackets, dots
  if (s.startsWith("+44")) s = "0" + s.slice(3);
  else if (s.startsWith("0044")) s = "0" + s.slice(4);
  else if (/^44\d{10}$/.test(s)) s = "0" + s.slice(2);   // "447700900123"
  return /^0\d{9,10}$/.test(s) ? s : null;
}

// 2. Patterns that run on the normalised digits
export const UK_MOBILE = /^07(?:[1-57-9]\d{8}|624\d{6})$/;            // not 070 or 076 (except 07624)
export const UK_PHONE  = /^0(?:1\d{8,9}|[2357]\d{9}|8\d{8,9}|9\d{9})$/; // any UK number type

export function isUkMobile(input) {
  const n = normaliseUkPhone(input);
  return n !== null && UK_MOBILE.test(n);
}
export function isUkPhone(input) {
  const n = normaliseUkPhone(input);
  return n !== null && UK_PHONE.test(n);
}

// 3. Store in E.164, show in the usual UK spacing
export function toE164(input) {
  const n = normaliseUkPhone(input);
  return n && UK_PHONE.test(n) ? "+44" + n.slice(1) : null;
}
export function formatUkPhone(input) {
  const n = normaliseUkPhone(input);
  if (!n || !UK_PHONE.test(n)) return null;
  if (n.startsWith("02")) return `${n.slice(0, 3)} ${n.slice(3, 7)} ${n.slice(7)}`; // 020 7946 0123
  if (/^07/.test(n)) return `${n.slice(0, 5)} ${n.slice(5)}`;                                         // 07700 900123
  if (/^01\d1|^011/.test(n) && n.length === 11) return `${n.slice(0, 4)} ${n.slice(4, 7)} ${n.slice(7)}`; // 0113 496 0123
  if (/^01/.test(n)) return `${n.slice(0, 5)} ${n.slice(5)}`;                                         // 01632 960123
  return `${n.slice(0, 4)} ${n.slice(4, 7)} ${n.slice(7)}`;                                           // 0808 157 0123
}

Step by step:

  1. normaliseUkPhone() trims the input, removes a (0), strips spaces, hyphens, brackets and dots, and converts +44, 0044 and a bare 44 followed by ten digits into a leading 0. If what's left isn't a 0 followed by 9 or 10 digits, it returns null. Letters, a missing 0 or the wrong length all fail here.
  2. The patterns only ever see clean digits, so they can be short. UK_MOBILE accepts 071 to 075 and 077 to 079, plus 07624. UK_PHONE accepts every UK number type: 01 with 9 or 10 more digits, 02, 03, 05 and 07 with 10 more, 08 with 9 or 10 more (some freephone numbers are shorter), and 09 with 10 more.
  3. toE164() returns the storage format and formatUkPhone() returns the display format, using the spacing people are used to: 07700 900123 for mobiles, 020 7946 0123 for London, 0113 496 0123 for the big cities with 011x and 01x1 codes, 01632 960123 for other areas, and 0808 157 0123 for everything else.

Here are 20 real-world inputs run through it:

// test.mjs: run the hand-written helpers over real-looking input
import { normaliseUkPhone, isUkMobile, isUkPhone, toE164, formatUkPhone } from "./uk-phone.mjs";

const inputs = [
  "07700 900123", "+44 7700 900123", "0044 7700 900 123", "+44 (0)7700 900123",
  "07700-900-123", "447700900123", "020 7946 0123", "(0113) 496 0123",
  "01632 960123", "0808 157 0123", "0306 999 0123", "0909 879 0123",
  "07400 123456", "070 1234 5678", "076 4012 3456", "07924 123456", "0612 345678", "7700 900123",
  "0770 090 012", "077009001234",
];
console.log("input".padEnd(20), "normalised".padEnd(12), "mobile", " any  ", "E.164".padEnd(14), "display");
for (const raw of inputs) {
  console.log(
    raw.padEnd(20),
    String(normaliseUkPhone(raw)).padEnd(12),
    String(isUkMobile(raw)).padEnd(6),
    String(isUkPhone(raw)).padEnd(6),
    String(toE164(raw)).padEnd(14),
    formatUkPhone(raw)
  );
}
$ node test.mjs
input                normalised   mobile  any   E.164          display
07700 900123         07700900123  true   true   +447700900123  07700 900123
+44 7700 900123      07700900123  true   true   +447700900123  07700 900123
0044 7700 900 123    07700900123  true   true   +447700900123  07700 900123
+44 (0)7700 900123   07700900123  true   true   +447700900123  07700 900123
07700-900-123        07700900123  true   true   +447700900123  07700 900123
447700900123         07700900123  true   true   +447700900123  07700 900123
020 7946 0123        02079460123  false  true   +442079460123  020 7946 0123
(0113) 496 0123      01134960123  false  true   +441134960123  0113 496 0123
01632 960123         01632960123  false  true   +441632960123  01632 960123
0808 157 0123        08081570123  false  true   +448081570123  0808 157 0123
0306 999 0123        03069990123  false  true   +443069990123  0306 999 0123
0909 879 0123        09098790123  false  true   +449098790123  0909 879 0123
07400 123456         07400123456  true   true   +447400123456  07400 123456
070 1234 5678        07012345678  false  true   +447012345678  07012 345678
076 4012 3456        07640123456  false  true   +447640123456  07640 123456
07924 123456         07924123456  true   true   +447924123456  07924 123456
0612 345678          0612345678   false  false  null           null
7700 900123          null         false  false  null           null
0770 090 012         0770090012   false  false  null           null
077009001234         null         false  false  null           null

The first six rows are the same mobile number typed six different ways: plain, with +44, with 0044, with +44 (0), with hyphens, and as 447700900123 with no plus. All six normalise to 07700900123, validate as a mobile, and come out as the same E.164 string and the same display format. That's the main point of normalising first: users type numbers however they like, and you shouldn't reject a correct number because of a space or a hyphen.

The rest of the table shows the edges:

  • London, Leeds, the "no area" 01632 range, freephone, UK-wide and premium numbers are all valid UK numbers but not mobiles, which is correct.
  • 07400 123456 and 07924 123456 (libphonenumber's own example mobiles) pass the mobile check.
  • 070 1234 5678 (a personal number) and 076 4012 3456 (a pager) are valid UK numbers but fail the strict mobile check. If you're collecting a number to send an SMS verification code to, that's what you want.
  • 0612 345678 fails, because 06 isn't used. 7700 900123 fails because the leading 0 is missing; I chose not to guess, but you could add it if your form makes the format clear. 0770 090 012 is a digit short, and 077009001234 is a digit too long.

One display quirk: my formatter shows the personal number as 07012 345678. Personal numbers are usually written 070 1234 5678, and libphonenumber gets that right, as you'll see below. If display spacing matters for every number type, that's a good reason to use the library.

The same thing in Python

The Python version mirrors the JavaScript one, using only the standard library's re module. I used fullmatch() rather than match() so the pattern has to cover the entire string, which saves you from forgetting the $ anchor:

"""uk_phone.py: normalise, validate and format UK phone numbers (standard library only)."""
import re

UK_MOBILE = re.compile(r"07(?:[1-57-9]\d{8}|624\d{6})")
UK_PHONE = re.compile(r"0(?:1\d{8,9}|[2357]\d{9}|8\d{8,9}|9\d{9})")


def normalise_uk_phone(text: str) -> str | None:
    s = str(text).strip().replace("(0)", "")
    s = re.sub(r"[\s\-().]", "", s)
    if s.startswith("+44"):
        s = "0" + s[3:]
    elif s.startswith("0044"):
        s = "0" + s[4:]
    elif re.fullmatch(r"44\d{10}", s):
        s = "0" + s[2:]
    return s if re.fullmatch(r"0\d{9,10}", s) else None


def is_uk_mobile(text: str) -> bool:
    n = normalise_uk_phone(text)
    return n is not None and UK_MOBILE.fullmatch(n) is not None


def is_uk_phone(text: str) -> bool:
    n = normalise_uk_phone(text)
    return n is not None and UK_PHONE.fullmatch(n) is not None


def to_e164(text: str) -> str | None:
    n = normalise_uk_phone(text)
    return "+44" + n[1:] if n and UK_PHONE.fullmatch(n) else None


if __name__ == "__main__":
    for raw in ["07700 900123", "+44 (0)7700 900123", "0044 7700-900-123",
                "020 7946 0123", "070 1234 5678", "7700 900123"]:
        print(f"{raw:20} mobile={is_uk_mobile(raw)!s:5}  any={is_uk_phone(raw)!s:5}  e164={to_e164(raw)}")
$ python3 uk_phone.py
07700 900123         mobile=True   any=True   e164=+447700900123
+44 (0)7700 900123   mobile=True   any=True   e164=+447700900123
0044 7700-900-123    mobile=True   any=True   e164=+447700900123
020 7946 0123        mobile=False  any=True   e164=+442079460123
070 1234 5678        mobile=False  any=True   e164=+447012345678
7700 900123          mobile=False  any=False  e164=None

The results agree with JavaScript row for row. +44 (0)7700 900123 and 0044 7700-900-123 both normalise to the same number, the London landline is valid but not a mobile, the 070 personal number is a valid UK number but not a mobile, and the number without its leading 0 is rejected. If you print these in a report or a table, f-string formatting is what lines up the columns, as in the {raw:20} above.

Keep the same rules on the server even if you check in the browser. Browser checks are for convenience: anyone can turn off JavaScript or send a request directly. If your form is handled by PHP, my guides to PHP form validation and sanitisation and the PHP contact form with mail() show where a check like this fits; PHP's preg_match accepts the same patterns.

Why the popular one-line UK mobile regex isn't enough

Search for "uk mobile number regex" and most answers give a single pattern that tries to handle the prefix and the spaces in one go. Here's a typical one, tested on raw input:

// oneline.mjs: the popular one-line regex, tested on raw input
const UK_MOBILE_RAW = /^(?:(?:\+|00)44\s?(?:\(0\)\s?)?|0)7\d{3}\s?\d{6}$/;
for (const raw of ["07700 900123", "+44 7700 900123", "0044 7700 900123", "+44 (0)7700 900123",
                   "07700 900 123", "07700-900-123", " 07700900123", "07012 345678"]) {
  console.log(JSON.stringify(raw).padEnd(22), UK_MOBILE_RAW.test(raw));
}
$ node oneline.mjs
"07700 900123"         true
"+44 7700 900123"      true
"0044 7700 900123"     true
"+44 (0)7700 900123"   true
"07700 900 123"        false
"07700-900-123"        false
" 07700900123"         false
"07012 345678"         true

It handles the four formats it was designed for, then fails three perfectly reasonable ones: 07700 900 123 (spaced 5-3-3, which plenty of people use), 07700-900-123 (hyphens), and " 07700900123" (a leading space, which happens all the time with copy and paste or autofill). It also accepts 07012 345678, a personal number, because 7\d{3} allows any 07 prefix. You could keep adding alternatives to the pattern, but each one makes it harder to read and easier to break. Normalising first, then matching a tiny pattern, avoids the whole problem. It's the same approach I recommended for email validation with regex: keep the pattern simple and handle the mess around it in plain code.

When to use libphonenumber instead of regex

A regex can tell you a number has the right shape. It can't tell you whether that range has actually been allocated. For that you need number-range data, and the standard source is Google's libphonenumber, available as libphonenumber-js for JavaScript and phonenumbers for Python. Here are the same kinds of input run through both:

// library.mjs: the same inputs through libphonenumber-js (full metadata)
import { parsePhoneNumberFromString } from "libphonenumber-js/max";
import pkg from "libphonenumber-js/package.json" with { type: "json" };

const inputs = ["07700 900123", "+44 (0)7700 900123", "020 7946 0123", "0113 496 0123",
  "01632 960123", "0808 157 0123", "0909 879 0123", "07400 123456", "070 1234 5678",
  "076 4012 3456", "07924 123456", "0612 345678", "0770 090 012"];
for (const raw of inputs) {
  const p = parsePhoneNumberFromString(raw, "GB");
  console.log(
    raw.padEnd(20),
    p ? `valid=${String(p.isValid()).padEnd(5)} type=${String(p.getType()).padEnd(15)} country=${p.country ?? "-"}  ${p.number}`
      : "could not parse"
  );
}
console.log("libphonenumber-js", pkg.version);
$ node library.mjs
07700 900123         valid=false type=undefined       country=GB  +447700900123
+44 (0)7700 900123   valid=false type=undefined       country=-  +447700900123
020 7946 0123        valid=true  type=FIXED_LINE      country=GB  +442079460123
0113 496 0123        valid=true  type=FIXED_LINE      country=GB  +441134960123
01632 960123         valid=false type=undefined       country=GB  +441632960123
0808 157 0123        valid=true  type=TOLL_FREE       country=GB  +448081570123
0909 879 0123        valid=true  type=PREMIUM_RATE    country=GB  +449098790123
07400 123456         valid=true  type=MOBILE          country=GB  +447400123456
070 1234 5678        valid=true  type=PERSONAL_NUMBER country=GB  +447012345678
076 4012 3456        valid=true  type=PAGER           country=GB  +447640123456
07924 123456         valid=true  type=MOBILE          country=GB  +447924123456
0612 345678          valid=false type=undefined       country=GB  +44612345678
0770 090 012         valid=false type=undefined       country=GB  +44770090012
libphonenumber-js 1.13.14
"""library.py: the same checks with the phonenumbers package (Python port of libphonenumber)."""
import phonenumbers
from phonenumbers import PhoneNumberFormat, PhoneNumberType, NumberParseException

TYPES = {v: k for k, v in vars(PhoneNumberType).items() if k.isupper()}

for raw in ["07700 900123", "+44 (0)7700 900123", "020 7946 0123", "07400 123456",
            "070 1234 5678", "0612 345678", "not a number"]:
    try:
        n = phonenumbers.parse(raw, "GB")
    except NumberParseException as e:
        print(f"{raw:20} parse error: {e}")
        continue
    print(f"{raw:20} valid={phonenumbers.is_valid_number(n)!s:5} "
          f"type={TYPES[phonenumbers.number_type(n)]:15} "
          f"e164={phonenumbers.format_number(n, PhoneNumberFormat.E164):14} "
          f"national={phonenumbers.format_number(n, PhoneNumberFormat.NATIONAL)}")
print("phonenumbers", phonenumbers.__version__)
$ python library.py   # inside a venv with phonenumbers installed
07700 900123         valid=False type=UNKNOWN         e164=+447700900123  national=07700 900123
+44 (0)7700 900123   valid=False type=UNKNOWN         e164=+447700900123  national=07700 900123
020 7946 0123        valid=True  type=FIXED_LINE      e164=+442079460123  national=020 7946 0123
07400 123456         valid=True  type=MOBILE          e164=+447400123456  national=07400 123456
070 1234 5678        valid=True  type=PERSONAL_NUMBER e164=+447012345678  national=070 1234 5678
0612 345678          valid=False type=UNKNOWN         e164=+44612345678   national=612345678
not a number         parse error: (1) The string supplied did not seem to be a phone number.
phonenumbers 9.0.40

Three results are worth pausing on:

  1. The Ofcom drama mobile 07700 900123 is invalid to both libraries (valid=false, type unknown), and so is the "no area" 01632 960123. Those ranges are deliberately never allocated, and the libraries know that. My regex accepts them, because they have the right shape. So use drama numbers to test your formatting and normalising code, but don't expect them to pass a library check, and use the library's example numbers (such as 07400 123456) to test library-based validation.
  2. The library tells you the type. PERSONAL_NUMBER for 070, PAGER for 076, TOLL_FREE for 0808, PREMIUM_RATE for 0909, FIXED_LINE for landlines and MOBILE for real mobile ranges. If you only want numbers that can receive a text, check getType() === "MOBILE" in JavaScript or number_type(n) == PhoneNumberType.MOBILE in Python.
  3. It formats correctly: 070 1234 5678 for the personal number, where my simple formatter gave 07012 345678. It also gives you E.164 directly with p.number or format_number(n, PhoneNumberFormat.E164).

I used the full "max" metadata in JavaScript (libphonenumber-js/max), because the smaller default build can't report number types. The library adds a noticeable amount of code to a page, so a sensible split is the regex in the browser for instant feedback, and the library on the server, where size doesn't matter. In Python, pip install phonenumbers inside a virtual environment is all you need; I tested version 9.0.40.

Neither approach proves a number is in use or belongs to the person typing it. If that matters, for example for two-factor login, send a one-time code by SMS and ask them to type it back.

Using the regex in an HTML form (and a pattern gotcha)

For a phone field, use <input type="tel" autocomplete="tel">. type="tel" doesn't validate anything by itself, because phone formats vary so much around the world, but it brings up the number keypad on phones, and autocomplete="tel" lets the browser fill in the user's number. I covered the other input types in HTML form input types and validation.

You can add a pattern attribute for a quick check before submit, but there's a trap. Current Chrome compiles pattern with the regex v flag, which is stricter about which characters can appear unescaped inside square brackets. I tested three versions of a loose "digits, spaces, plus and brackets" pattern:

// pattern.mjs: does an <input pattern> for UK phone numbers actually validate?
import puppeteer from "puppeteer-core";
const browser = await puppeteer.launch({ executablePath: "/usr/bin/google-chrome", headless: true, args: ["--no-sandbox"] });
const page = await browser.newPage();
const warnings = [];
page.on("console", m => warnings.push(m.text()));
await page.setContent(`
  <input id="a" type="tel" pattern="[0-9 +()-]{10,20}">
  <input id="b" type="tel" pattern="[0-9 +()\\-]{10,20}">
  <input id="c" type="tel" pattern="[0-9 +\\(\\)\\-]{10,20}">`);
const patterns = await page.$$eval("input", els => els.map(e => e.getAttribute("pattern")));
for (const value of ["07700 900123", "+44 (0)20 7946 0123", "call me maybe"]) {
  const res = await page.evaluate(v => [...document.querySelectorAll("input")].map(i => {
    i.value = v; return i.checkValidity();
  }), value);
  console.log(JSON.stringify(value).padEnd(24), "a:", String(res[0]).padEnd(6), "b:", String(res[1]).padEnd(6), "c:", res[2]);
}
patterns.forEach((p, i) => console.log("abc"[i], "=", p));
console.log("console:", warnings.length ? "\n  " + warnings.join("\n  ") : "(none)");
await browser.close();
$ node pattern.mjs
"07700 900123"           a: true   b: true   c: true
"+44 (0)20 7946 0123"    a: true   b: true   c: true
"call me maybe"          a: true   b: true   c: false
a = [0-9 +()-]{10,20}
b = [0-9 +()\-]{10,20}
c = [0-9 +\(\)\-]{10,20}
console: 
  Pattern attribute value [0-9 +()-]{10,20} is not a valid regular expression: Uncaught SyntaxError: Failed to execute 'checkValidity' on 'HTMLInputElement': Invalid regular expression: /[0-9 +()-]{10,20}/v: Invalid character in character class
  Pattern attribute value [0-9 +()\-]{10,20} is not a valid regular expression: Uncaught SyntaxError: Failed to execute 'checkValidity' on 'HTMLInputElement': Invalid regular expression: /[0-9 +()\-]{10,20}/v: Invalid character in character class

Patterns a and b look fine and would work as a normal JavaScript regex, but Chrome reports Invalid character in character class and ignores the pattern completely. As a result, "call me maybe" passed validation. No error appears on the page; the only clue is a message in the developer console. Pattern c, with (, ) and - all escaped, works, and correctly rejects the text. If you use pattern, escape every symbol inside the brackets, then test it with something that should fail, not just with something that should pass.

In practice, I keep the HTML pattern loose (or leave it out), normalise and validate with JavaScript on blur or submit so I can show a helpful message, and validate again on the server.

Common mistakes with UK phone number validation

  1. Validating the raw input with one big pattern. It rejects real numbers with spaces or hyphens and is hard to maintain. Normalise first.
  2. Forgetting the anchors. Without ^ and $ (or Python's fullmatch), a pattern can match part of a longer string, so 0770090012300000 would pass a check for 11 digits.
  3. Storing numbers formatted. Store E.164 (+447700900123) in the database and format on display. Otherwise searching and de-duplicating become painful.
  4. Treating every 07 number as a mobile. 070 and 076 aren't mobiles. If you send SMS, use the strict mobile pattern or the library's type.
  5. Storing phone numbers as integers. The leading 0 disappears and the + can't be stored. Phone numbers are text that happens to contain digits.
  6. Using real-looking made-up numbers in tests and demos. Use Ofcom's drama ranges or the library's example numbers instead.
  7. Escaping problems in pattern. As shown above, an invalid pattern quietly turns off validation.

FAQ

What is the regex for a UK mobile number?

After removing spaces and converting +44 to 0, use ^07\d{9}$, which matches 07 followed by nine digits. To exclude 070 personal numbers and 076 pagers, use ^07(?:[1-57-9]\d{8}|624\d{6})$. Testing raw input with one pattern is possible but rejects common formats such as 07700 900 123.

How do I validate a UK phone number in JavaScript?

Normalise the input by removing spaces, hyphens, brackets and dots, and converting a leading +44, 0044 or 44 to 0. Then test it against /^0(?:1\d{8,9}|[2357]\d{9}|8\d{8,9}|9\d{9})$/ for any UK number, or a mobile pattern. Use libphonenumber-js if you need to check that the range has been allocated.

How many digits is a UK phone number?

Most UK numbers are 11 digits including the leading 0, such as 07700 900123 or 020 7946 0123. A few landline areas and some freephone numbers have 10. In international format the 0 is dropped and +44 is added, so a mobile is +44 followed by 10 digits.

How do I write a UK number with the country code?

Drop the leading 0 and add +44, so 07700 900123 becomes +44 7700 900123, or +447700900123 without spaces (E.164). Don't write +44 (0)7700 900123. It's common, but the 0 shouldn't be dialled after +44.

Should I use regex or libphonenumber for phone validation?

Use a regex for quick format checks and instant feedback in the browser. Use libphonenumber (libphonenumber-js or Python's phonenumbers) when you need to know whether a number is in an allocated range, what type it is, or how to format it correctly. In my tests, the libraries rejected Ofcom's unallocated drama numbers, while a regex accepted them.

// note

How to read this note.

This is a learning note from studying the web. It is one small topic, written so I can remember it. It is not a course and not a claim that I have finished the subject.

If a sentence is wrong, say so from the contact page and name this title. Drafts never appear here. Related notes, when they exist, are other published posts, and the same sample rule applies to each of them.

Related notes

CSS Text Overflow Ellipsis: 1 Line, 2 Lines and Flexbox
Coding tips

CSS Text Overflow Ellipsis: 1 Line, 2 Lines and Flexbox

One-line ellipsis needs white-space: nowrap, overflow: hidden and text-overflow: ellipsis. Tested fixes for flexbox, grid and tables, plus 2- and 3-line truncation with line-clamp.

October 6, 2026 · 15 min read · 0 views

Git Delete Branch Local and Remote (Tested Commands)
Coding tips

Git Delete Branch Local and Remote (Tested Commands)

git branch -d name deletes the local branch, git push origin --delete name deletes the remote one. Tested errors, pruning stale branches, bulk clean-ups and how to undo a delete.

October 6, 2026 · 19 min read · 0 views

JavaScript Sort Array of Objects by Property (Tested)
Coding tips

JavaScript Sort Array of Objects by Property (Tested)

Pass sort() a compare function: a.price - b.price for numbers, a.name.localeCompare(b.name) for strings. Dates, multiple properties, toSorted() and the mistakes to avoid, all tested.

October 6, 2026 · 20 min read · 0 views