
What is a fully qualified domain name (FQDN)?
A fully qualified domain name (FQDN) is the complete, unambiguous name of a host or service in DNS, spelling out every label from the host itself all the way up to the root. www.example.com. is an FQDN: it names the host www, in the domain example, under the top-level domain com, under the root. Strictly speaking, an FQDN ends with a trailing dot, which represents the root of the DNS tree, although in everyday use people usually leave it off and still call www.example.com an FQDN. The opposite is a relative or partially qualified name, such as www or db, which only makes sense once a domain is added to it.
The idea is simple, but it shows up in a surprising number of places: zone files, SSL certificates, mail server settings, Kubernetes, Windows networking and the search domains on your laptop. In this article you'll learn how an FQDN is structured, the length and character rules, why the trailing dot matters, how operating systems turn short names into FQDNs, how to find your own machine's FQDN, and how to validate one in code.
The Structure of an FQDN
An FQDN is a list of labels separated by dots, read from the most specific on the left to the most general on the right:
api.eu.example.com.
│ │ │ │ └── root (the empty label)
│ │ │ └───── top-level domain (TLD)
│ │ └───────────── second-level domain (registered name)
│ └──────────────── subdomain
└──────────────────── host name
Each label is one level of the DNS tree. Together they describe a single, exact path from the root down to one node. That's what makes the name "fully qualified": nothing is left to be filled in by context.
Host Name vs Domain Name vs FQDN
These terms overlap, so it helps to pin them down:
| Term | Example | Meaning |
|---|---|---|
| Host name | api | The name of one machine or service, without its domain |
| Domain name | eu.example.com | A node in DNS and everything below it |
| FQDN | api.eu.example.com. | The host name plus every domain above it, up to the root |
| Relative name | api or api.eu | A name that needs a suffix added before it can be looked up |
| URL | https://api.eu.example.com/v1/users | A full resource address that contains an FQDN as its host part |
An FQDN can also refer to a name that isn't a machine at all. example.com. is itself an FQDN, as is _dmarc.example.com., which holds a TXT record for email policy.
The Rules: Length and Characters
Length Limits
- Each label can be 1 to 63 characters long.
- The whole name can be at most 253 characters in its usual text form without the trailing dot. On the wire, DNS encodes names with a length byte before each label, and the limit there is 255 bytes, which works out to 253 visible characters.
- A name can have up to 127 labels in theory, though you'll never come close in practice.
Allowed Characters
DNS itself can technically store almost any byte in a label, but host names follow stricter rules that date back to RFC 952 and RFC 1123, often called the LDH rule (letters, digits, hyphen):
- Letters
atoz, case-insensitive. - Digits
0to9. - Hyphens
-, but not at the start or end of a label.
Some special-purpose names use underscores, such as _dmarc.example.com or _sip._tcp.example.com. That's allowed because those names hold records like TXT and SRV rather than identifying hosts. You shouldn't use underscores in names you intend to connect to, such as web servers, because browsers, certificate authorities and other software may reject them.
Case
DNS names are case-insensitive. WWW.Example.COM. and www.example.com. are the same FQDN. Servers generally preserve the case you used in the query, but comparisons ignore it.
Internationalised Names
Names with non-ASCII characters, such as café.example, are stored in DNS in an ASCII form called punycode, prefixed with xn--. The browser or application converts them automatically:
dig xn--caf-dma.example A +short
So café.example. and xn--caf-dma.example. are the same FQDN; the second is just how DNS sees it.
Why the Trailing Dot Matters
The final dot represents the root of the DNS tree, whose label is empty. Including it tells software, "This name is complete. Don't add anything to it."
In most everyday contexts the dot is implied and you never type it. A browser treats www.example.com as complete. But in some places the difference between www.example.com and www.example.com. is critical.
In Zone Files
In a DNS zone file, a name without a trailing dot is relative to the zone's origin. In the example.com zone:
$ORIGIN example.com.
www IN CNAME shop.example.net. ; correct: points to shop.example.net
blog IN CNAME shop.example.net ; wrong: points to shop.example.net.example.com.
The second record is one of the most common DNS mistakes. You'll see the result if you query it:
dig blog.example.com CNAME +short
shop.example.net.example.com.
In Command-Line Tools
dig doesn't apply search domains unless you ask it to, so dig db and dig db. both look up a single-label name. But nslookup, host, ping, ssh and most applications do use your search list. Adding a trailing dot forces the name to be treated as fully qualified and skips the search list entirely:
ping -c 1 db.example.com.
That's useful when a search domain is causing a lookup to go somewhere unexpected.
In URLs
https://www.example.com./ is technically a valid URL pointing at the same host, but some websites and CDNs don't recognise the dotted form in the HTTP Host header or match it to their certificates, so it may fail or behave differently. Leave it out of links and redirects.
Search Domains: How Short Names Become FQDNs
When you type ssh db on a company laptop and it works, your operating system has quietly turned db into an FQDN using a search list.
On Linux
The search list lives in /etc/resolv.conf, often managed by systemd-resolved, NetworkManager or DHCP:
nameserver 192.0.2.53
search corp.example.com example.com
options ndots:1
With this configuration, looking up db:
dbhas fewer dots thanndots(1), so the resolver tries the search list first.- It asks for
db.corp.example.com.If that exists, it stops there. - Otherwise it tries
db.example.com. - Finally it tries
db.on its own.
A name with at least ndots dots, such as db.example.com, is tried as-is first, and the search list is only used if that fails.
You can watch this happen with dig, which needs the +search option to use the list, plus +showsearch to print each attempt:
dig +search +showsearch db A
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50211
;; QUESTION SECTION:
;db.corp.example.com. IN A
;; ANSWER SECTION:
db.corp.example.com. 300 IN A 192.0.2.40
On systems using systemd-resolved, you can see the configured search domains with:
resolvectl domain
Global:
Link 2 (eth0): corp.example.com example.com
On Windows
Windows has a primary DNS suffix for the computer (set by joining a domain or in the system properties) and connection-specific suffixes supplied by DHCP. Both are used to complete short names. You can view them in PowerShell:
Get-DnsClientGlobalSetting | Select-Object SuffixSearchList
Get-DnsClient | Select-Object InterfaceAlias, ConnectionSpecificSuffix
And set a custom search list:
Set-DnsClientGlobalSetting -SuffixSearchList @("corp.example.com", "example.com")
In Kubernetes
Kubernetes pods get a search list such as default.svc.cluster.local svc.cluster.local cluster.local and, by default, ndots:5. That means a name like api.example.com (two dots) is first tried with every search suffix before being looked up as written, which can multiply DNS traffic. Writing external names as true FQDNs with a trailing dot, such as api.example.com., skips those extra lookups.
Search Domain Pitfalls
- Unexpected matches: If
corp.example.comcontains a wildcard record, every short name may resolve to it. - Leaked queries: Short names that don't exist internally are often sent to public resolvers, revealing internal naming.
- Slow failures: Each suffix in the list is a separate lookup, so a long list makes typos slow to fail.
- Name collisions: A short name that happens to match a new public TLD, or a suffix that's a real public domain you don't own, can send traffic somewhere you never intended.
Using FQDNs in configuration files, scripts and application settings avoids all of these.
Finding Your Machine's FQDN
Linux
hostname # short host name
hostname -f # FQDN, as resolved by the system
hostnamectl # host name details on systemd systems
web01
web01.corp.example.com
hostname -f works out the FQDN using the system's resolver configuration, which often means the /etc/hosts file. A common, correct layout is:
127.0.0.1 localhost
192.0.2.21 web01.corp.example.com web01
The FQDN must come first, followed by any short aliases. If they're the wrong way round, hostname -f returns just the short name.
macOS
hostname
scutil --get HostName
Windows
[System.Net.Dns]::GetHostEntry($env:COMPUTERNAME).HostName
web01.corp.example.com
In Code
Most languages can return the local machine's FQDN. In Python:
import socket
print(socket.getfqdn())
Be aware that socket.getfqdn() relies on reverse lookups and local configuration, so on a laptop it may return something unexpected, such as a .local name or a reverse DNS name.
Where You Need an FQDN
- SSL/TLS certificates: Certificates are issued for FQDNs, such as
www.example.comor a wildcard like*.example.com. Public certificate authorities won't issue certificates for short names likeintranet. - Mail servers: A mail server should greet others with a valid FQDN that resolves in DNS, and its reverse DNS should match. In Postfix, that's the
myhostnamesetting, for examplemyhostname = mail.example.com. - Zone file targets: The data in
CNAME,MX,NS,SRVandPTRrecords should be FQDNs ending in a dot, unless you deliberately use relative names. - Configuration files: Database connection strings, API endpoints and service discovery work more reliably with FQDNs than with names that depend on the search list.
- Kerberos and Active Directory: Service principal names and domain joins depend on correct FQDNs.
Validating an FQDN in Python
When you accept host names in an application, such as a domain verification form or a configuration tool, it's worth checking them properly. This script checks the trailing dot, converts internationalised labels to punycode, and enforces the label and length rules for host names:
import re
import sys
LABEL = re.compile(r"^(?!-)[a-z0-9-]{1,63}(?<!-)$", re.IGNORECASE)
def to_ascii(label):
"""Convert one label to its ASCII (punycode) form if needed."""
if label.isascii():
return label
return label.encode("idna").decode("ascii")
def check_fqdn(name):
"""Return a list of problems with a host name written as an FQDN."""
problems = []
if not name.endswith("."):
problems.append("missing trailing dot (relative, not fully qualified)")
name += "."
ascii_labels = []
for label in name[:-1].split("."):
if not label:
problems.append("empty label (two dots in a row?)")
continue
try:
label = to_ascii(label)
except UnicodeError:
problems.append(f"label cannot be converted to ASCII: {label!r}")
continue
if len(label) > 63:
problems.append(f"label longer than 63 characters: {label[:20]}...")
elif not LABEL.match(label):
problems.append(f"invalid host name label: {label!r}")
ascii_labels.append(label)
length = len(".".join(ascii_labels))
if length > 253:
problems.append(f"name too long: {length} characters (max 253)")
return problems
for arg in sys.argv[1:]:
issues = check_fqdn(arg)
print(f"{arg}: {'OK' if not issues else '; '.join(issues)}")
Run it with a few test names:
python3 fqdn.py www.example.com. www.example.com -bad-.example.com. café.example. a..example.com. under_score.example.com.
www.example.com.: OK
www.example.com: missing trailing dot (relative, not fully qualified)
-bad-.example.com.: invalid host name label: '-bad-'
café.example.: OK
a..example.com.: empty label (two dots in a row?)
under_score.example.com.: invalid host name label: 'under_score'
Python's built-in idna codec implements the older IDNA 2003 standard. If you need the newer IDNA 2008 rules, the third-party idna package is the usual choice. In many applications you'll want to accept names without the trailing dot and add it yourself, since most users never type it.
FAQ: Fully Qualified Domain Names
Yes. An FQDN doesn't have to include a host name like www. example.com. is fully qualified because it specifies the complete path from the root. In casual use, example.com without the trailing dot is also called an FQDN.
Almost never in browsers or everyday tools. It matters in DNS zone files, where a missing dot makes a name relative, and it can be useful on the command line to stop the system from adding search domains.
253 characters in normal text form, with each label limited to 63 characters. The underlying DNS wire format allows 255 bytes, which includes length bytes for each label.
An FQDN is just the name of a host, such as www.example.com. A URL is a complete address for a resource, which includes a scheme, the FQDN as its host, and optionally a port, path and query, like https://www.example.com/pricing.
PQDN stands for partially qualified domain name. It's a relative name, such as db or db.corp, that needs a suffix added from a search list or zone origin before it can be resolved.
Names used for special records, such as _dmarc or _sip._tcp, commonly contain underscores, and DNS allows them. Host names you connect to should stick to letters, digits and hyphens, because many applications and certificate authorities reject underscores in host names.
Usually because /etc/hosts lists the short name before the FQDN, or the system can't resolve its own name. Put the FQDN first on the line for the machine's IP address, followed by the short alias.
Conclusion
A fully qualified domain name is a name with nothing left to guess: every label from the host up to the root, ideally finished with the trailing dot that represents the root itself. Relative names are convenient, but they depend on context, whether that's a zone's origin or your system's search list, and context can change.
Use FQDNs wherever precision matters: in zone file targets, certificates, mail server settings, configuration files and anything running in Kubernetes. Keep labels within 63 characters and the whole name within 253, stick to letters, digits and hyphens for host names, and remember that one missing dot in a zone file can quietly send traffic to the wrong place.


