Common Patterns: URL & Phone — Regex

Validasi URL URL memiliki struktur yang cukup kompleks. Mari bangun pattern-nya bertahap. Struktur URL https://www.example.com:8080/path/page?key=value#section

Validasi URL

URL memiliki struktur yang cukup kompleks. Mari bangun pattern-nya bertahap.

Struktur URL

https://www.example.com:8080/path/page?key=value#section
|_____|  |_____________||__||_________||________||______|
protocol    host        port   path     query     hash

Pattern URL Sederhana

const simpleUrl = /^https?:\/\/[\w.-]+\.[a-zA-Z]{2,}/;

simpleUrl.test("https://google.com");           // true
simpleUrl.test("http://localhost");              // false (tidak ada TLD)
simpleUrl.test("ftp://file.server.com");        // false (bukan http/s)

Pattern URL Lebih Lengkap

const urlRegex = /^https?:\/\/[\w.-]+\.[a-zA-Z]{2,}(:\d+)?(\/[\w./-]*)?/;

urlRegex.test("https://belajarweb.dev");           // true
urlRegex.test("http://api.example.com:3000");      // true
urlRegex.test("https://web.dev/learn/css");        // true
urlRegex.test("bukan-url");                        // false

Mari bedah:

Extract URL dari Teks

const teks = "Kunjungi https://belajarweb.dev atau http://example.com/page untuk info lebih lanjut";
const urls = teks.match(/https?:\/\/[\w.-]+\.[a-zA-Z]{2,}(\/[\w./?&=#-]*)?/g);
console.log(urls);
// ["https://belajarweb.dev", "http://example.com/page"]

Validasi Nomor Telepon Indonesia

Nomor telepon Indonesia punya beberapa format yang umum:

Format yang Perlu Didukung

08123456789      (tanpa separator)
0812-3456-789    (dengan dash)
0812 3456 789    (dengan spasi)
+628123456789    (dengan kode negara)
+62-812-3456-789 (kode negara dengan dash)
(021) 1234567    (telepon rumah)

Pattern untuk Nomor HP

// Nomor HP Indonesia — format 08xx atau +62
const hpRegex = /^(\+62|0)8\d{1,2}[- ]?\d{4}[- ]?\d{2,4}$/;

hpRegex.test("081234567890");     // true
hpRegex.test("0812-3456-7890");   // true
hpRegex.test("+6281234567890");   // true
hpRegex.test("021-1234567");     // false (bukan HP)

Normalisasi Nomor Telepon

Seringkali kita perlu mengubah berbagai format ke satu format standar:

function normalizePhone(phone) {
  // Hapus semua non-digit kecuali +
  let clean = phone.replace(/[^\d+]/g, "");

  // Ubah 08xx ke +628xx
  if (clean.startsWith("0")) {
    clean = "+62" + clean.slice(1);
  }

  return clean;
}

console.log(normalizePhone("0812-3456-7890"));  // "+6281234567890"
console.log(normalizePhone("+62 812 3456 789")); // "+62812345678 9"
console.log(normalizePhone("081234567890"));     // "+6281234567890"

Validasi dengan Named Groups

function parsePhoneNumber(phone) {
  const regex = /^(?<prefix>\+62|0)(?<operator>8\d{1,2})[- ]?(?<middle>\d{4})[- ]?(?<last>\d{2,4})$/;
  const match = phone.match(regex);

  if (!match) return null;

  return {
    prefix: match.groups.prefix,
    operator: match.groups.operator,
    number: match.groups.middle + match.groups.last,
    formatted: `+62${match.groups.operator}-${match.groups.middle}-${match.groups.last}`
  };
}

console.log(parsePhoneNumber("0812-3456-7890"));
// { prefix: "0", operator: "812", number: "34567890", formatted: "+62812-3456-7890" }

Format Otomatis Saat Mengetik

function formatPhoneInput(value) {
  const digits = value.replace(/\D/g, "");

  if (digits.length <= 4) return digits;
  if (digits.length <= 8) return digits.slice(0, 4) + "-" + digits.slice(4);
  return digits.slice(0, 4) + "-" + digits.slice(4, 8) + "-" + digits.slice(8, 12);
}

console.log(formatPhoneInput("081234567890")); // "0812-3456-7890"

Format Internasional E.164

Standar internasional untuk nomor telepon adalah E.164: diawali +, kode negara, lalu nomor lokal — total maksimal 15 digit, tanpa spasi atau separator.

// E.164: ^+ diikuti 1 digit non-nol, lalu 1-14 digit
const e164 = /^\+[1-9]\d{1,14}$/;

e164.test("+6281234567890");  // true (Indonesia)
e164.test("+14155552671");    // true (US)
e164.test("+442071838750");   // true (UK)
e164.test("+0812345");        // false (kode negara tidak boleh diawali 0)
e164.test("081234567890");    // false (tidak ada +)

Catatan: Validasi Kode Negara di Regex Tidak Praktis

Setiap negara punya panjang dan format nomor yang berbeda. Memvalidasi semua aturan ini hanya dengan regex akan sangat panjang dan rapuh — kode area baru bisa muncul kapan saja, dan beberapa negara punya panjang nomor yang bervariasi.

Untuk production, pakai library yang dimaintain Google:

// npm install libphonenumber-js
import { parsePhoneNumber, isValidPhoneNumber } from "libphonenumber-js";

isValidPhoneNumber("+6281234567890");           // true
parsePhoneNumber("0812-3456-7890", "ID").number; // "+6281234567890"

Library ini di-update mengikuti perubahan numbering plan tiap negara — sesuatu yang regex statismu tidak akan pernah bisa lakukan.

Regex sangat powerful untuk validasi dan transformasi format data — tapi ingat, untuk validasi production, selalu kombinasikan dengan server-side validation.

🎭 Analogi sehari-hari: URL = alamat rumah lengkap. Protokol = "Jakarta vs Surabaya" (kota). Domain = nama jalan. Path = nomor rumah. Query = note tambahan. Phone Indonesia = nomor PLN: prefix kode area + nomor pelanggan. Format beragam (08xx, +628xx, 628xx) — semua valid, tinggal normalize ke satu format.

💡 libphonenumber > regex untuk phone: Google maintain database global (panjang nomor, format, valid prefix per negara, mobile vs landline). Regex statis = ketinggalan terus. Pakai libphonenumber-js (15kb gzipped) untuk production.

⚠️ Jebakan klasik:

🎯 URL/phone validation strategy:

TL;DR: URL dan phone format kompleks. Regex sederhana untuk basic check, library untuk production. URL: pakai new URL() constructor di JS. Phone: pakai libphonenumber-js. Normalize input sebelum validate.