New blogMaking an AI Agent You Can Trust With Money

★ Web · regex

Regex for Domain Name

Checks a bare domain name: labels of letters, digits and inner hyphens, up to 63 characters each, separated by dots and ending in a letters-only TLD. Punycode labels (xn--) for internationalised domains pass.

  • Runs in your browser
  • No signup

Try the domain name pattern

Read it in plain English (best-effort)

  • ^start of a line
  • (?:start a group (not captured)
  • [A-Za-z0-9]one character from: A–Z, a–z, 0–9
  • (?:start a group (not captured)
  • [A-Za-z0-9-]one character from: A–Z, a–z, 0–9, '-'
  • {0,61}between 0 and 61 of the previous
  • [A-Za-z0-9]one character from: A–Z, a–z, 0–9
  • )end of group
  • ?the previous is optional
  • .the character '.'
  • )end of group
  • +one or more of the previous
  • [A-Za-z]one character from: A–Z, a–z
  • {2,63}between 2 and 63 of the previous
  • $end of a line

One sample per line works well with the m flag on anchored patterns.

Waiting for a pattern
01

The pattern, piece by piece

/^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}$/
Pattern explanation
PartWhat it does
[A-Za-z0-9]a label starts with a letter or digit
(?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?up to 63 characters, not ending in a hyphen
\.a dot between labels
+one or more labels
[A-Za-z]{2,63}the top-level domain
02

What it accepts and rejects

Every sample below is checked automatically in JavaScript and Python. The tester above is preloaded with all of them, one per line.

Should match
Should match
example.com✓
sub.example.co.uk✓
my-site.dev✓
x.ai✓
a1.b2.io✓
xn--80ak6aa92e.com✓
Should not match
Should not match
-example.com✗
example-.com✗
example✗
example..com✗
exa mple.com✗
http://example.com✗
03

Copy it into your code

RE2-safeNo lookarounds or backreferences, so the same pattern works in Go's RE2 engine and in Rust's regex crate.

const domainRe = /^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}$/;

export function isValidDomain(value) {
  return domainRe.test(value.trim());
}
04

When not to use regex for this

To know whether a domain actually exists or is available, you need DNS or RDAP lookups, not a pattern. The regex doesn't enforce the 253-character total length limit either; check string length separately if it matters.

05

Questions engineers actually ask

Does it support emoji or non-Latin domains?
Only in their punycode form (xn--…). Convert with the URL API or a punycode library before validating.
Why isn't the 253-character limit checked?
Enforcing it in regex needs a lookahead, which Go's RE2 engine doesn't support. A length check in code is clearer anyway.
What is catastrophic backtracking?
Some patterns, usually nested quantifiers like (a+)+, make a backtracking engine try an exponential number of paths on input that almost matches. The tester stops any run after 300ms, so a bad pattern can't freeze your tab. In production, that same pattern can take down a server (a ReDoS attack).
06

More web patterns

07

More from the workbench

Fine print

Tools: on the house.
Engineer: by the hour.

The regex was free. Code that doesn't need one is the upgrade: typed schemas, validated once at the edge, trusted everywhere after.

I'm Himanshu, an AI and full-stack engineer. I build MVPs, AI agents and the growth plumbing around them for early-stage startups.