Skip to main content

Command Palette

Search for a command to run...

Regex Patterns for API Validation: Email, URL, Phone (Copy-Paste Ready)

Published
11 min readView as Markdown

return (

/ Schema.org JSON-LD /

/ Breadcrumb Navigation /

Home / Blog / Regex Validation Patterns

/ Article Header /

# Regex Patterns for API Validation: Email, URL, Phone (Copy-Paste Ready)

Regex March 6, 2026 14 min read

/ Article Content /

Why Regex Validation Matters for APIs

Every API that accepts user input needs validation. Unvalidated data leads to database corruption, injection attacks, broken downstream systems, and poor user experience. Regular expressions are the most common tool for format validation -- checking that an email looks like an email, a URL looks like a URL, and a phone number contains the right digits.

This guide provides production-ready regex patterns you can copy directly into your codebase. Each pattern includes a practical version (good enough for 99% of cases) and a strict version (for compliance-heavy applications). All patterns have been tested against real-world edge cases, including internationalized inputs and adversarial strings.

Test any pattern from this guide instantly with our Regex Tester tool. Paste the pattern, add test strings, and see matches highlighted in real time -- all in your browser, no server required.

Email Validation Regex

Email validation is the most common and most debated regex use case. The full RFC 5322 specification is absurdly complex (it allows quoted strings, comments, and folding whitespace), so in practice, developers choose between a simple format check and a more thorough pattern. The truth is that the only way to truly validate an email is to send a verification message to it.

This pattern covers 99.9% of real email addresses. It ensures there is a local part, an @ symbol, a domain, and a TLD. It deliberately avoids being overly strict so it does not reject valid but unusual addresses.

`// Simple email regex -- covers 99.9% of real addresses const EMAIL_SIMPLE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

// Test cases: EMAIL_SIMPLE.test('user@example.com'); // true EMAIL_SIMPLE.test('user+tag@example.com'); // true EMAIL_SIMPLE.test('user@sub.domain.com'); // true EMAIL_SIMPLE.test('user@example.co.uk'); // true EMAIL_SIMPLE.test('user@example'); // false (no TLD) EMAIL_SIMPLE.test('@example.com'); // false (no local) EMAIL_SIMPLE.test('user @example.com'); // false (space) EMAIL_SIMPLE.test(''); // false (empty)`

Stricter Email Regex (HTML5 Standard)

This pattern is based on the HTML5 specification for '' validation. It is more restrictive about allowed characters in the local and domain parts while still accepting all common email formats.

// HTML5 spec email regex const EMAIL_HTML5 = /^[a-zA-Z0-9.!#$%&'*+/=?^_\|~-]+@a-zA-Z0-9?(?:\.a-zA-Z0-9?)*$/;

// Python equivalent:

import re

EMAIL_HTML5 = re.compile(

r"^[a-zA-Z0-9.!#$%&'*+/=?^_`|~-]+@"

r"a-zA-Z0-9?"

r"(?:\.a-zA-Z0-9?)*$"

)`

Email Validation in Practice

`// Production email validation function function validateEmail(email) // Step 1: Basic format check with regex const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!pattern.test(email)) return valid: false, error: 'Invalid email format' ;

// Step 2: Length check (RFC 5321 limits) const [local, domain] = email.split('@'); if (local.length > 64) return valid: false, error: 'Local part exceeds 64 characters' ;

if (domain.length > 253) return valid: false, error: 'Domain exceeds 253 characters' ;

// Step 3: Check for disposable email domains (optional) const disposable = ['tempmail.com', 'throwaway.email', 'guerrillamail.com']; if (disposable.includes(domain.toLowerCase())) return valid: false, error: 'Disposable email addresses not allowed' ;

return valid: true ;

// Step 4 (server-side): Send verification email // This is the ONLY way to truly validate an email address`

URL Validation Regex

URL validation is another case where regex works well for basic checks but falls short for complete RFC 3986 compliance. For most APIs, you need to validate that a string is a well-formed HTTP or HTTPS URL with a valid domain.

Practical URL Regex

`// URL regex -- HTTP/HTTPS with domain validation const URLPATTERN = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%.+~#=]1,256\.[a-zA-Z0-9()]1,6\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/;

// Test cases: URL_PATTERN.test('https://example.com'); // true URL_PATTERN.test('https://www.example.com/page'); // true URL_PATTERN.test('http://sub.domain.co.uk/path?q=1'); // true URL_PATTERN.test('https://example.com/path#section'); // true URL_PATTERN.test('ftp://example.com'); // false URL_PATTERN.test('example.com'); // false URL_PATTERN.test('https://'); // false`

Better Approach: Use the URL Constructor

For JavaScript and Node.js, the built-in URL constructor is more reliable than any regex. It parses URLs according to the WHATWG URL Standard and throws on invalid input.

`// URL validation using the URL constructor (recommended) function validateUrl(input) try const url = new URL(input);

// Optional: restrict to HTTP/HTTPS if (!['http:', 'https:'].includes(url.protocol)) return valid: false, error: 'Only HTTP and HTTPS URLs are allowed' ;

// Optional: block localhost and private IPs (SSRF prevention) const hostname = url.hostname; if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname.startsWith('192.168.') || hostname.startsWith('10.') || hostname.startsWith('172.16.')) return valid: false, error: 'Private URLs not allowed' ;

return valid: true, parsed: url ; catch return valid: false, error: 'Invalid URL format' ;

// Python equivalent:

from urllib.parse import urlparse

def validate_url(input_url):

try:

result = urlparse(input_url)

return all([result.scheme in ('http', 'https'), result.netloc])

except ValueError:

return False`

Slug and Path Validation

`// URL slug (kebab-case, lowercase, no special chars) const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;

SLUG.test('my-blog-post'); // true SLUG.test('post-123'); // true SLUG.test('My-Post'); // false (uppercase) SLUG.test('-leading-dash'); // false SLUG.test('trailing-dash-'); // false SLUG.test('double--dash'); // false

// URL path segment (allows slashes) const URL_PATH = /^\/(?:[a-z0-9-]+\/)*[a-z0-9-]+\/?$/;

URL_PATH.test('/blog/my-post'); // true URL_PATH.test('/api/v2/users/'); // true`

Phone Number Validation Regex

Phone number validation is notoriously difficult because formats vary wildly by country. A US number looks like (555) 123-4567, a UK number looks like +44 7911 123456, and a Japanese number looks like 090-1234-5678. For production applications, use Google's libphonenumber library. For basic format checking, these patterns work as a first pass.

US Phone Number

`// US phone: (xxx) xxx-xxxx, xxx-xxx-xxxx, xxx.xxx.xxxx, xxxxxxxxxx const US_PHONE = /^(?:\+1\s?)?(?:\(?\\d3\)?[\s.-]?)\d3[\s.-]?\d4$/;

US_PHONE.test('(555) 123-4567'); // true US_PHONE.test('555-123-4567'); // true US_PHONE.test('555.123.4567'); // true US_PHONE.test('5551234567'); // true US_PHONE.test('+1 555 123 4567'); // true US_PHONE.test('123-456'); // false (too short) US_PHONE.test('(555) 123-45678'); // false (too long)`

International Phone (E.164 Format)

`// E.164 format: + country code + subscriber number (7-15 digits total) const E164_PHONE = /^\+?[1-9]\d6,14$/;

E164_PHONE.test('+14155552671'); // true (US) E164_PHONE.test('+447911123456'); // true (UK) E164_PHONE.test('+5511987654321'); // true (Brazil) E164_PHONE.test('+81901234567'); // true (Japan) E164_PHONE.test('+0123456789'); // false (starts with 0) E164_PHONE.test('+123'); // false (too short)`

Phone Validation in Practice

`// Normalize phone input before validation function normalizePhone(input) // Strip everything except digits and leading + return input.replace(/(?!^\+)[^\d]/g, '');

function validatePhone(input, country = 'US') const cleaned = normalizePhone(input);

const patterns = US: /^\+?1?\d10$/, UK: /^\+?44\d10$/, BR: /^\+?55\d10,11$/, E164: /^\+?[1-9]\d6,14$/, // International fallback ;

const pattern = patterns[country] || patterns.E164; return pattern.test(cleaned);

// For production: use libphonenumber // npm install google-libphonenumber // const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance(); // const number = phoneUtil.parse('+14155552671', 'US'); // phoneUtil.isValidNumber(number); // true`

Date and Time Validation Regex

Date validation with regex checks the format but not the logic (February 30th passes a format check but is not a real date). Use regex for format enforcement and a date library for logical validation.

`// ISO 8601 date: YYYY-MM-DD const ISO_DATE = /^\d4-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/;

ISO_DATE.test('2026-03-06'); // true ISO_DATE.test('2026-12-31'); // true ISO_DATE.test('2026-13-01'); // false (month 13) ISO_DATE.test('2026-00-15'); // false (month 00) ISO_DATE.test('26-03-06'); // false (2-digit year)

// ISO 8601 datetime with timezone: YYYY-MM-DDTHH:MM:SSZ const ISO_DATETIME = /^\d4-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|+-:[0-5]\d)$/;

ISO_DATETIME.test('2026-03-06T14:30:00Z'); // true ISO_DATETIME.test('2026-03-06T14:30:00+05:30'); // true ISO_DATETIME.test('2026-03-06T14:30:00.123Z'); // true ISO_DATETIME.test('2026-03-06T25:00:00Z'); // false (hour 25)

// Time only: HH:MM or HH:MM:SS (24-hour) const TIME_24H = /^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$/;

TIME_24H.test('14:30'); // true TIME_24H.test('14:30:59'); // true TIME_24H.test('24:00'); // false TIME_24H.test('2:30'); // false (need leading zero)

// Complete date validation (format + logic) function isValidDate(dateString) if (!/^\d4-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/.test(dateString)) return false; // Format check

const date = new Date(dateString); const [year, month, day] = dateString.split('-').map(Number); // Logic check: does the parsed date match the input? return date.getFullYear() === year && date.getMonth() + 1 === month && date.getDate() === day;

isValidDate('2026-02-28'); // true isValidDate('2026-02-29'); // false (2026 is not a leap year) isValidDate('2024-02-29'); // true (2024 is a leap year)`

Additional Useful Patterns

Beyond emails, URLs, and phones, here are other common validation patterns you will need when building APIs. Each pattern is ready to copy into your codebase.

Password Strength

`// Strong password: 8+ chars, uppercase, lowercase, digit, special char const STRONG_PASSWORD = /^(?=.[a-z])(?=.[A-Z])(?=.\d)(?=.[@$!%?&])[A-Za-z\d@$!%?&]8,$/;

STRONG_PASSWORD.test('MyP@ss1word'); // true STRONG_PASSWORD.test('weakpass'); // false (no uppercase, digit, special) STRONG_PASSWORD.test('Short1!'); // false (less than 8 chars)

// Note: NIST now recommends checking passwords against breach databases // (Have I Been Pwned API) rather than enforcing complex rules. // Minimum 8 characters + breach check > complex regex rules`

Username

`// Username: 3-20 chars, alphanumeric + underscore/hyphen // Must start with a letter const USERNAME = /^[a-zA-Z][a-zA-Z0-9_-]2,19$/;

USERNAME.test('john_doe'); // true USERNAME.test('dev-user123'); // true USERNAME.test('ab'); // false (too short) USERNAME.test('1user'); // false (starts with number) USERNAME.test('user name'); // false (space)`

IPv4 and IPv6 Addresses

`// IPv4: 0.0.0.0 to 255.255.255.255 const IPV4 = /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.)3(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/;

IPV4.test('192.168.1.1'); // true IPV4.test('10.0.0.255'); // true IPV4.test('256.1.1.1'); // false (256 > 255) IPV4.test('1.2.3'); // false (only 3 octets)

// IPv6 (simplified -- accepts most common formats) const IPV6 = /^(?:[0-9a-fA-F]1,4:)7[0-9a-fA-F]1,4$/;

IPV6.test('2001:0db8:85a3:0000:0000:8a2e:0370:7334'); // true`

Credit Card Number (Luhn-checkable formats)

`// Major card formats (format check only -- always use Luhn + processor) const VISA = /^4\d12(?:\d3)?$/; // Starts with 4, 13 or 16 digits const MASTERCARD = /^5[1-5]\d14$/; // Starts with 51-55, 16 digits const AMEX = /^3[47]\d13$/; // Starts with 34/37, 15 digits

// Strip spaces/dashes before testing const cleaned = '4111 1111 1111 1111'.replace(/[\s-]/g, ''); VISA.test(cleaned); // true

// Always validate with Luhn algorithm + payment processor function luhnCheck(num) let sum = 0; let even = false; for (let i = num.length - 1; i >= 0; i--) let digit = parseInt(num[i], 10); if (even) digit *= 2; if (digit > 9) digit -= 9; sum += digit; even = !even;

return sum % 10 === 0; `

Hex Color Code

`// Hex color: #RGB or #RRGGBB (with optional alpha) const HEX_COLOR = /^#(?:[0-9a-fA-F]3,4|[0-9a-fA-F]6|[0-9a-fA-F]8)$/;

HEX_COLOR.test('#fff'); // true (shorthand) HEX_COLOR.test('#FF5733'); // true (6-digit) HEX_COLOR.test('#FF573380'); // true (8-digit with alpha) HEX_COLOR.test('#gggggg'); // false (invalid hex chars) HEX_COLOR.test('FF5733'); // false (no #)`

Quick Reference Table

Copy the pattern you need from this summary table. Test them all in our Regex Tester before deploying.

Input Pattern Notes

Email (simple)'/^[^\s@]+@[^\s@]+\.[^\s@]+$/'Good for 99.9% of emails URL (HTTP/S)'Use new URL() constructor'More reliable than regex US Phone'/^(?:\+1\s?)?(?:\(?\\d3\)?[\s.-]?)\d3[\s.-]?\d4$/'All common US formats Intl Phone'/^\+?[1-9]\d6,14$/'E.164 format ISO Date'/^\d4-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/'YYYY-MM-DD format only Password'8+ chars, upper+lower+digit+special'Prefer breach DB check IPv4'0-255 per octet, 4 groups'Full range validation Hex Color'#RGB, #RRGGBB, #RRGGBBAA'With optional alpha

Avoiding Over-Engineering: When Regex Is Not the Answer

Regex is a powerful tool, but it is not always the right one. Over-engineered regex patterns become maintenance nightmares, introduce subtle bugs, and give a false sense of security. Here are cases where you should use a different approach.

  • Email deliverability -- No regex can tell you if an email exists. Send a verification email instead of trying to catch every edge case with a 5,000-character pattern.
  • URL parsing -- The URL constructor in JavaScript (or urlparse in Python) handles edge cases that regex misses, including punycode, IPv6 hosts, and port numbers.
  • International phone numbers -- Country-specific rules are too complex for regex. Use libphonenumber for production validation.
  • HTML parsing -- Famously, regex cannot parse HTML. Use a DOM parser (DOMParser, Cheerio, BeautifulSoup).
  • JSON validation -- Use JSON.parse() in a try-catch, not regex. For complex validation, use a JSON validator with schema support.

`// Use validation libraries for complex schemas // Zod (TypeScript-first schema validation)

const UserSchema = z.object( email: z.string().email(), name: z.string().min(2).max(100), age: z.number().int().min(13).max(150), website: z.string().url().optional(), phone: z.string().regex(/^\+?[1-9]\d6,14$/), );

// Validates and returns typed data or throws const user = UserSchema.parse(req.body);

// Joi (Node.js validation) const Joi = require('joi'); const schema = Joi.object( email: Joi.string().email().required(), phone: Joi.string().pattern(/^\+?[1-9]\d6,14$/), );`

Client-Side vs Server-Side Validation

A common mistake is treating client-side validation as a security measure. Client-side regex provides instant feedback for the user, but it can be bypassed by anyone using browser developer tools, curl, or Postman. Always validate on both sides.

Aspect Client-Side Server-Side

PurposeUser experience (instant feedback)Security (data integrity) Bypassable?Yes (always)No (unless server is compromised) SpeedInstant (no network round-trip)Requires API call Error messagesInline, field-levelReturned in API response Required?Nice to haveMandatory

`// Client-side: instant UX feedback

// Server-side: the actual validation (Express middleware) function validateBody(schema) return (req, res, next) => const error, value = schema.validate(req.body, abortEarly: false, // Return ALL errors, not just the first stripUnknown: true, // Remove unknown fields );

if (error) return res.status(400).json( errors: error.details.map(d => ( field: d.path.join('.'), message: d.message, )), );

req.validatedBody = value; next(); ;

app.post('/api/users', validateBody(userSchema), createUser);`

/ FAQ Section /

Frequently Asked Questions

What is the best regex for email validation?

For most applications, the practical pattern '/^[^\s@]+@[^\s@]+\.[^\s@]+$/' is sufficient. It catches obvious errors (missing @, no domain) without rejecting valid edge cases. For strict RFC 5322 compliance, use a dedicated email validation library instead of regex, as the full specification is too complex for a single pattern.

Should I use regex or a library for input validation?

Use regex for simple format checks (does it look like an email?) and libraries for strict validation (is it a deliverable email?). Libraries like Zod, Yup, and joi provide composable validation with better error messages. For URLs, the built-in URL constructor in JavaScript is more reliable than any regex.

Why does my email regex reject valid addresses?

Common reasons include: not allowing + tags (user+tag@example.com), not supporting new TLDs longer than 3 characters (.technology, .museum), not handling subdomains (user@mail.example.com), or requiring specific TLD formats. The safest approach is to validate loosely (has @ and a dot after it) and confirm via a verification email.

How do I validate international phone numbers with regex?

International phone numbers vary so widely in format that no single regex handles all cases reliably. Use the libphonenumber library (Google) for production validation. For a basic format check, '/^\+?[1-9]\d6,14$/' matches E.164 format which covers most international numbers after stripping spaces and dashes.

Is client-side regex validation enough for security?

No. Client-side validation is for user experience only -- it provides instant feedback but can be bypassed by anyone using browser dev tools, curl, or Postman. Always validate on the server side as well. Client-side regex catches typos; server-side validation prevents malicious input. Both layers are necessary for a secure application.

/ CTA Section /

Test Your Regex Patterns

Paste any regex pattern into our free Regex Tester to see matches highlighted in real time. Test against multiple input strings, view capture groups, and debug your patterns. Everything runs locally in your browser.

Open Regex Tester

/ Related Articles /

[

Regex Cheat Sheet

Complete reference for regex syntax, quantifiers, anchors, and lookaheads.

](/blog/regex-cheat-sheet/) [

How to Format JSON

Format and validate JSON payloads from API responses and config files.

](/blog/json-formatting-guide/) [

HTTP Status Codes Guide

Understand 400 Bad Request and other validation error responses.

](/blog/http-status-codes-guide/) [

JWT vs Session Cookies

Compare authentication methods for APIs that need input validation.

](/blog/jwt-vs-session-cookies-authentication/)

)


Originally published on bytepane.com. Visit for free interactive calculators and tools.

More from this blog

R

Brazora

91 posts