How to validate a domain name using Regex & Php?
The accepted answer is incomplete/wrong.
The regex pattern;
should NOT validate domains such as:
-example.com
,example--.com
,-example-.-.com
,example.000
, etc...should validate domains such as:
schools.k12
,newTLD.clothing
,good.photography
, etc...
After some further research; below is the most correct, cross-language and compact pattern I could come up with:
^(?!\-)(?:(?:[a-zA-Z\d][a-zA-Z\d\-]{0,61})?[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63}$
This pattern conforms with most* of the rules defined in the specs:
- Each label/level (splitted by a dot) may contain up to 63 characters.
- The full domain name may have up to 127 levels.
- The full domain name may not exceed the length of 253 characters in its textual representation.
- Each label can consist of letters, digits and hyphens.
- Labels cannot start or end with a hyphen.
- The top-level domain (extension) cannot be all-numeric.
Note 1: The full domain length check is not included in the regex. It should be simply checked by native methods e.g. strlen(domain) <= 253
.
Note 2: This pattern works with most languages including PHP, Javascript, Python, etc...
See DEMO here (for JS, PHP, Python)
More Info:
The regex above does not support IDNs.
There is no spec that says the extension (TLD) should be between 2 and 6 characters. It actually supports 63 characters. See the current TLD list here. Also, some networks do internally use custom/pseudo TLDs.
Registration authorities might impose some extra, specific rules which are not explicitly supported in this regex. For example,
.CO.UK
and.ORG.UK
must have at least 3 characters, but less than 23, not including the extension. These kinds of rules are non-standard and subject to change. Do not implement them if you cannot maintain.Regular Expressions are great but not the best effective, performant solution to every problem. So a native URL parser should be used instead, whenever possible. e.g. Python's
urlparse()
method or PHP'sparse_url()
method...After all, this is just a format validation. A regex test does not confirm that a domain name is actually configured/exists! You should test the existence by making a request.
Specs & References:
- IETF: RFC1035
- IETF: RFC1123
- IETF: RFC2181
- IETF: RFC952
- Wikipedia: Domain Name System
UPDATE (2019-12-21): Fixed leading hyphen with subdomains.
How about:
^(?:[-A-Za-z0-9]+\.)+[A-Za-z]{2,6}$
In my case, domain name is considered as valid if the format is stackoverflow.com
or xxx.stackoverflow.com
So in addition to other stack answers, I have added checking for www.
also.
function isValidDomainName($domain) {
if (filter_var(gethostbyname($domain), FILTER_VALIDATE_IP)) {
return (preg_match('/^www./', $domain)) ? FALSE : TRUE;
}
return FALSE;
}
you can test the function with this code
$domain = array("http://www.domain.example","http://www.domain.example/folder" ,"http://domain.example", "www.domain.example", "domain.example/subfolder", "domain.example","sub.domain.example");
foreach ($domain as $v) {
echo isValidDomainName($v) ? "{$v} is valid<br>" : "{$v} is invalid<br>";
}
Please try this expression:
^(http[s]?\:\/\/)?((\w+)\.)?(([\w-]+)?)(\.[\w-]+){1,2}$
What it actually does
- optional
http/s://
- optional
www
- any valid alphanumeric name (including
-
and_
) - 1 or 2 occurrences of any valid alphanumeric name (including
-
and_
)
Validation Examples
http://www.test.example
test.com.mt