Regex for Domain Names
A domain is a series of labels separated by dots, ending in a top-level domain. Each label is 1–63 letters, digits or hyphens and can't start or end with a hyphen, and the whole name is at most 253 characters. This pattern enforces all of that and expects at least two labels.
/^(?=.{1,253}$)(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,63}$/How it works, token by token
| Token | Meaning |
|---|---|
| ^(?=.{1,253}$) | lookahead: the whole name is 1–253 characters long |
| (?: | start of a label-plus-dot group |
| (?!-) | the label can't start with a hyphen |
| [A-Za-z0-9-]{1,63} | 1 to 63 letters, digits or hyphens |
| (?<!-)\. | the label can't end with a hyphen; then a dot |
| )+ | one or more labels |
| [A-Za-z]{2,63}$ | a top-level domain of 2–63 letters, then end of string |
What it matches
example.comsub.domain.co.ukxn--bcher-kva.examplea-b.io-example.comexample-.comlocalhostexample.cTry it live
One candidate per line — the m flag makes the ^ and $ anchors apply to each line. Edit anything; it runs in your browser.
Variations
^(?=.{1,253}$)(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+(?:[A-Za-z]{2,63}|xn--[A-Za-z0-9-]{1,59})$also allow punycode top-level domains such as xn--p1ai (.рф)^(?:\*\.)?(?=.{1,253}$)(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,63}$also allow a leading wildcard (*.example.com)Language notes
- The lookbehind (?<!-) needs ES2018+ in JavaScript (every current browser and Node.js). Python, .NET and PCRE support it; Go's RE2 does not, so check label edges in code there.
Frequently asked questions
Does this accept internationalised domains like bücher.de?
Only in punycode form (xn--bcher-kva.de). Convert input first — in JavaScript, new URL("http://" + input).hostname does it — then validate.
Why does localhost fail?
The pattern requires at least one dot and a top-level domain. If your app needs single-label hosts, allow them separately.
Building something custom? The regex tester gives you live match highlighting for any pattern.