Domain Name Regex
Validates a fully qualified domain name made of one or more dot-separated labels followed by an alphabetic top-level domain, rejecting labels that start or end with a hyphen.
Regex Pattern
^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$Pattern Breakdown
Hover over a token to see what it does.
| Token | Meaning |
|---|---|
| ^ | Anchors the match to the start of the string |
| (?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+ | Non-capturing group repeated one or more times, one per domain label plus its trailing dot |
| [a-zA-Z0-9] | A label must start with a letter or digit |
| (?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? | Optional middle and final characters of the label, allowing hyphens only in the interior |
| \. | Literal dot separating each label |
| [a-zA-Z]{2,63} | The top-level domain, requiring 2 to 63 alphabetic characters |
| $ | Anchors the match to the end of the string |
Detailed Explanation
What it does
This pattern checks that a string is a syntactically valid domain name: one or more labels separated by dots, each label starting and ending with an alphanumeric character, followed by a purely alphabetic top-level domain of at least two characters.
Why it works
The repeated group `(?:label\.)+` consumes every label up through its trailing dot, including subdomains, while the final `[a-zA-Z]{2,63}` requires the TLD to be letters only, matching how real TLDs like com, io, or travel are formed. Requiring the first and last character of each label to be alphanumeric (rather than the whole label) correctly rejects labels that start or end with a hyphen, which DNS itself disallows.
Common use cases
- Validating a custom domain field when a user configures a website or email service
- Parsing and sanity-checking domains extracted from log files or referrer headers
- Filtering a list of URLs down to those with syntactically valid domain names before a DNS lookup
- Client-side validation for domain-purchase or DNS-management forms
Edge cases
- Internationalized domain names (IDN) with non-ASCII characters will not match unless first converted to Punycode
- New-style numeric or very long TLDs beyond 63 characters are still accepted by the {2,63} bound
- A domain with a trailing dot representing the DNS root, like example.com., is rejected by this pattern
- Single-label hostnames without any dot, such as localhost, are intentionally rejected since they lack a TLD
Limitations
- Does not verify that the domain is actually registered or resolvable via DNS
- Does not support Punycode-encoded internationalized domains without pre-processing
- Total domain length (max 253 characters) is not enforced separately from per-label limits
- Cannot distinguish between reserved/unassigned TLDs and real, in-use ones
Interactive Tester
Edit the pattern or text below — matching runs live in your browser.
Test Cases
Editable — add your own inputs to see if they pass.
| Input | Expected | Result | |
|---|---|---|---|
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass |
Language Variants
Production-ready examples in 12 languages.
const domainRegex = /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,63}$/;
console.log(domainRegex.test('example.com')); // trueCommon Mistakes
Allowing hyphens anywhere in a label, including at the start or end
Fix: Constrain the first and last character of each label to alphanumerics, allowing hyphens only in the interior via `[a-zA-Z0-9-]{0,61}[a-zA-Z0-9]`
Forgetting that a domain needs at least one dot before the TLD
Fix: Use a `+` quantifier on the label group so at least one label-plus-dot is required before the final TLD segment
Allowing digits in the top-level domain segment
Fix: Restrict the final TLD segment to `[a-zA-Z]{2,63}` since real TLDs are alphabetic
Performance Notes
- Each label is bounded to 63 characters via the {0,61} quantifier, preventing unbounded backtracking on pathological input
- The repeated group has a clear terminating dot, so the engine does not need to backtrack across label boundaries
- For validating many domains in bulk, compile the regex once and reuse it rather than reconstructing it per call
Browser Compatibility
| Engine | Supported | Notes |
|---|---|---|
| Chrome | Yes | — |
| Firefox | Yes | — |
| Safari | Yes | — |
| Edge | Yes | — |
| Node.js | Yes | — |