Utilo

Domain Name Regular Expression – Free, Online, Private

Matches a dotted domain with labels that do not start or end with a hyphen.

Tester
Sample
Matches (2)
  • example.com
  • tools.tech4dream.com

The pattern

The pattern requires at least one dot, so localhost does not match and example.com does. Each label starts and ends with a letter or digit. Hyphens may appear in the middle. The last label is alphabetic and at least two characters, so example.c fails and example.com succeeds. tools.tech4dream.com matches. A label longer than 63 characters fails the quantifier. The i flag makes the case irrelevant.

The source is ^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$. The flags on this page are im. i means case-insensitive. m means ^ and $ match at line breaks, which is how the sample can show several candidates. g is not set. The tester finds non-overlapping matches, and without g a pattern with no anchor still reports the matches it walks. The box under the title is a tester with this pattern and the sample already filled in. Edit either one. Nothing you type is uploaded. The same tester, without a preset, is the regex tool.

How to read it

The repeated group is one label and a dot. [a-zA-Z0-9] is the first character. (?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? is the optional rest: up to 61 middle characters, which may be hyphens, and a final alphanumeric. That is a 63-character label. The + requires at least one such label-and-dot. [a-zA-Z]{2,} is the final label, the TLD, and it cannot contain a digit. Anchors and m test lines. A trailing dot, which DNS allows for the root, is not accepted.

What it will not do

Internationalized names must be in punycode (xn--) before this pattern sees them. A raw Unicode label fails. The pattern does not check that the TLD is delegated. example.notathing matches the shape. It does not match a single-label host, a trailing dot, or an empty label from a double dot. It is not a URL pattern. Paste a host, not a URL with a path. The URL pattern is the one that wants a scheme.

A match is not a parsed value. An email pattern does not send mail, a UUID pattern does not allocate an id, and a password pattern does not store a password. When the next step needs a real parser, use one: the URL constructor, a date library, a semver library, or the converters on this site. The expression is the part you can see.

JavaScript, Python, and Go

The JavaScript snippet uses the RegExp constructor so the source does not have to be escaped for a literal slash. The Python snippet uses a normal string with the same escapes JSON would emit, which keeps \d as a regex digit class. Go's snippet uses a raw string. If the pattern contains a lookahead, the Go snippet says so and does not call MustCompile, because RE2 would reject it at runtime.

JavaScriptconst re = new RegExp("^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}$", "im");
const found = text.match(re);
console.log(found ? found[0] : "no match");
Pythonimport re

pattern = re.compile("^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}$", re.IGNORECASE | re.MULTILINE)
found = pattern.search(text)
print(found.group(0) if found else "no match")
Gopackage main

import (
	"fmt"
	"regexp"
)

func main() {
	text := ""
	re := regexp.MustCompile(`(?i)(?m)^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$`)
	fmt.Println(re.FindString(text))
}

Frequently asked questions

Does localhost match?

No. The pattern requires a dot and a final alphabetic label.

Can a label start with a hyphen?

No. The first and last character of a label are alphanumeric.

Are Unicode domains matched?

Only after they are converted to punycode. The pattern is ASCII.

Does a trailing dot match?

No. example.com. is rejected. Strip the root dot if you accept it elsewhere.