
What is an SRV record and which services use it?
An SRV (service) record is a DNS record that tells clients which host and port provide a particular service for a domain. Where an A record only gives an IP address and an MX record only works for email, an SRV record can describe any service: it names the service and protocol, gives a hostname and port number, and adds priority and weight values so clients can fail over between servers and spread the load. Defined in RFC 2782, it's used by VoIP, chat, directory services, calendars, game servers, and databases, among others.
SRV records let you move a service to a different server or port without reconfiguring every client, as long as the client software supports SRV lookups. In this article you'll learn how SRV records are named and structured, how priority and weight work together, which services actually use them and the names they expect, how to create and query SRV records, and the limitations to be aware of, including why web browsers don't use them.
How an SRV Record Is Structured
An SRV record has a special naming format and four data fields:
_sip._tcp.example.com. 3600 IN SRV 10 60 5060 sip1.example.com.
The Name: _service._protocol.domain
The record name is built from three parts:
- _sip: The symbolic name of the service, with a leading underscore.
- _tcp: The transport protocol, usually
_tcpor_udp. Some services use_tlsas well. - example.com.: The domain the service belongs to.
The underscores keep these names from clashing with real hostnames, which can't contain underscores. A client that wants to find the SIP service for example.com over TCP knows to look up exactly _sip._tcp.example.com.
The Data Fields
| Field | Example | Meaning |
|---|---|---|
| Priority | 10 | Lower values are tried first, like MX priority |
| Weight | 60 | Relative share of traffic among records with the same priority |
| Port | 5060 | The TCP or UDP port the service listens on |
| Target | sip1.example.com. | The hostname of the server providing the service |
All three numbers are 16-bit values from 0 to 65535. The target must be a hostname with its own A or AAAA records. It mustn't be a CNAME, and it can't be an IP address.
A target of a single dot (.) has a special meaning: the service is deliberately not available at this domain. That lets clients stop looking instead of trying fallbacks.
_xmpp-server._tcp.example.com. 3600 IN SRV 0 0 0 .
How Priority and Weight Work Together
Priority and weight solve two different problems.
Priority for Failover
A client always tries the records with the lowest priority first. It only moves to the next priority level when every server at the current level has failed:
_sip._tcp.example.com. 3600 IN SRV 10 50 5060 sip1.example.com.
_sip._tcp.example.com. 3600 IN SRV 10 50 5060 sip2.example.com.
_sip._tcp.example.com. 3600 IN SRV 20 0 5060 sip-backup.example.net.
Here sip1 and sip2 share the work, and sip-backup only receives traffic if both are down.
Weight for Load Distribution
Among records with the same priority, the client picks one at random in proportion to its weight. With weights of 60 and 40, roughly 60% of clients choose the first server and 40% the second:
_sip._tcp.example.com. 3600 IN SRV 10 60 5060 big.example.com.
_sip._tcp.example.com. 3600 IN SRV 10 40 5060 small.example.com.
Weights are relative, so 60 and 40 behave the same as 3 and 2. A weight of 0 means the record should be chosen only very rarely when other records at that priority have higher weights. If you don't need weighting, give every record the same value.
The Selection Algorithm in Code
RFC 2782 describes exactly how clients should order records. This Python script uses dnspython to look up SRV records and order them the way a compliant client would:
import random
import sys
import dns.resolver
def weighted_order(records):
"""Order same-priority records using the RFC 2782 weighting method."""
remaining = sorted(records, key=lambda r: r.weight) # zero weights first
ordered = []
while remaining:
total = sum(r.weight for r in remaining)
pick = random.randint(0, total)
running = 0
for record in remaining:
running += record.weight
if running >= pick:
ordered.append(record)
remaining.remove(record)
break
return ordered
def srv_order(name):
answers = dns.resolver.resolve(name, "SRV")
by_priority = {}
for record in answers:
by_priority.setdefault(record.priority, []).append(record)
result = []
for priority in sorted(by_priority):
result.extend(weighted_order(by_priority[priority]))
return result
if __name__ == "__main__":
name = sys.argv[1] if len(sys.argv) > 1 else "_sip._tcp.example.com"
for r in srv_order(name):
target = str(r.target)
if target == ".":
print("Service explicitly not available")
break
print(f"priority={r.priority:<5} weight={r.weight:<5} {target}:{r.port}")
pip install dnspython
python srv_order.py _sip._tcp.example.com
priority=10 weight=60 big.example.com.:5060
priority=10 weight=40 small.example.com.:5060
priority=20 weight=0 sip-backup.example.net.:5060
Run it a few times and the order within priority 10 will change in roughly a 60/40 split.
Which Services Use SRV Records?
SRV records only help if the client software looks them up. These are the most common services that do, along with the names they expect.
VoIP and SIP
SIP phones and softphones use SRV records (RFC 3263) to find the SIP server for a domain, so users can sign in with just alice@example.com:
_sip._udp.example.com. 3600 IN SRV 10 50 5060 sip.example.com.
_sip._tcp.example.com. 3600 IN SRV 10 50 5060 sip.example.com.
_sips._tcp.example.com. 3600 IN SRV 10 50 5061 sip.example.com.
XMPP Chat
XMPP (RFC 6120) uses separate records for client connections and for server-to-server federation:
_xmpp-client._tcp.example.com. 3600 IN SRV 5 0 5222 chat.example.com.
_xmpp-server._tcp.example.com. 3600 IN SRV 5 0 5269 chat.example.com.
Active Directory and Kerberos
Windows domains depend heavily on SRV records. Domain-joined computers find domain controllers, Kerberos servers and global catalogue servers through records that the domain controllers register automatically in DNS:
_ldap._tcp.dc._msdcs.corp.example.com. 600 IN SRV 0 100 389 dc1.corp.example.com.
_kerberos._tcp.corp.example.com. 600 IN SRV 0 100 88 dc1.corp.example.com.
_gc._tcp.corp.example.com. 600 IN SRV 0 100 3268 dc1.corp.example.com.
When computers can't find a domain controller, missing or stale SRV records are one of the first things to check. On a Windows machine, nltest /dsgetdc:corp.example.com uses the same lookups.
Calendars and Contacts
CalDAV and CardDAV clients (RFC 6764) can discover servers through SRV records, often paired with a TXT record that gives the path:
_caldavs._tcp.example.com. 3600 IN SRV 0 1 443 dav.example.com.
_carddavs._tcp.example.com. 3600 IN SRV 0 1 443 dav.example.com.
_caldavs._tcp.example.com. 3600 IN TXT "path=/dav/calendars"
Email Client Configuration
RFC 6186 and RFC 8314 define SRV records that let mail apps discover IMAP and submission servers. Support varies by client, but publishing them does no harm:
_imaps._tcp.example.com. 3600 IN SRV 0 1 993 imap.example.com.
_submissions._tcp.example.com. 3600 IN SRV 0 1 465 smtp.example.com.
_submission._tcp.example.com. 3600 IN SRV 0 1 587 smtp.example.com.
Microsoft Outlook also checks _autodiscover._tcp as one of its fallback methods for finding the Autodiscover service.
Game Servers
Minecraft Java Edition looks up _minecraft._tcp, which lets players connect to play.example.com even when the server runs on a non-default port:
_minecraft._tcp.play.example.com. 3600 IN SRV 0 5 25570 mc1.example.com.
Databases and Platforms
- MongoDB: Connection strings beginning
mongodb+srv://cluster0.example.commake the driver look up_mongodb._tcp.cluster0.example.comto find every member of the cluster, plus a TXT record for connection options. - Matrix: Homeservers find each other for federation through
_matrix-fed._tcp, with.well-knownfiles as the preferred method. - Kubernetes: Cluster DNS creates SRV records for named ports on services, such as
_http._tcp.my-svc.my-namespace.svc.cluster.local.
Why Browsers Don't Use SRV Records
It's a common wish to publish _http._tcp.example.com and run a website on port 8080 without the port appearing in the URL. Unfortunately, web browsers don't look up SRV records for HTTP. HTTP was standardised long before SRV, and browser vendors never adopted it because of the extra lookup latency and backwards-compatibility concerns.
The modern answer for web traffic is the HTTPS DNS record type, which can advertise alternative ports and protocols and which major browsers do support. For everything else, check the documentation of the client software. If it doesn't mention SRV, assume it doesn't use it.
Creating SRV Records
In a Zone File
$ORIGIN example.com.
_sip._tcp 3600 IN SRV 10 60 5060 sip1.example.com.
_sip._tcp 3600 IN SRV 10 40 5060 sip2.example.com.
sip1 3600 IN A 192.0.2.21
sip2 3600 IN A 192.0.2.22
In a Web Dashboard
Many DNS provider dashboards split an SRV record into separate fields: service, protocol, name, priority, weight, port and target. Others ask for a full record name such as _sip._tcp and a combined value such as 10 60 5060 sip1.example.com. If the dashboard appends your domain automatically, enter only _sip._tcp as the name, or you'll end up with _sip._tcp.example.com.example.com.
With the AWS CLI on Route 53
Route 53 expects the value as a single string of priority, weight, port and target:
cat > srv.json <<'EOF'
{
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "_sip._tcp.example.com",
"Type": "SRV",
"TTL": 3600,
"ResourceRecords": [
{ "Value": "10 60 5060 sip1.example.com" },
{ "Value": "10 40 5060 sip2.example.com" }
]
}
}
]
}
EOF
aws route53 change-resource-record-sets \
--hosted-zone-id Z0123456789EXAMPLE \
--change-batch file://srv.json
Querying SRV Records
With dig
dig _sip._tcp.example.com SRV +noall +answer
_sip._tcp.example.com. 3600 IN SRV 10 60 5060 sip1.example.com.
_sip._tcp.example.com. 3600 IN SRV 10 40 5060 sip2.example.com.
Authoritative servers often include the targets' A and AAAA records in the additional section, saving the client a second lookup. You can see them by dropping +noall +answer.
With nslookup
nslookup -type=srv _sip._tcp.example.com
_sip._tcp.example.com service = 10 60 5060 sip1.example.com.
_sip._tcp.example.com service = 10 40 5060 sip2.example.com.
With PowerShell
Resolve-DnsName -Name _ldap._tcp.dc._msdcs.corp.example.com -Type SRV
Testing the Port
Once you know the target and port, check that the service is actually listening:
nc -vz sip1.example.com 5060
A DNS record pointing at a closed port looks correct in every DNS tool but still fails for users.
Common SRV Record Mistakes
- Missing underscores:
sip.tcp.example.comisn't an SRV name. It must be_sip._tcp.example.com. - Doubling the domain: Dashboards that append the zone name can turn
_sip._tcp.example.cominto_sip._tcp.example.com.example.com. Query the record to confirm the final name. - Pointing the target at a CNAME or an IP: The target must be a hostname with address records.
- Wrong protocol label: Publishing
_udpwhen the client looks for_tcp, or the other way round. - Expecting browsers to use it: SRV records don't change how websites load.
- Forgetting the firewall: The record advertises a port, but the port still has to be open.
FAQ: SRV Records
Priority decides the order in which groups of servers are tried, with lower numbers first. Weight decides how traffic is shared between servers that have the same priority, in proportion to their weight values.
No. Web browsers don't use SRV records for HTTP or HTTPS. To serve a site on a non-standard port without showing it, use a reverse proxy on port 443 instead.
It shouldn't be. RFC 2782 requires the target to be a hostname with A or AAAA records. Some clients follow a CNAME anyway, but others don't, so point the target at the real host.
It means the service is deliberately not offered at that domain. Clients that see it should stop looking rather than trying fallback methods.
For basic email, no. Microsoft 365 may still list SRV records for some older or hybrid scenarios, so follow the records your admin centre shows for your tenant rather than a generic list.
Check its documentation for SRV or DNS-based service discovery. If the client asks you for a hostname and port separately and says nothing about SRV, it probably doesn't look them up.
Conclusion
An SRV record combines a service name, a protocol, a hostname and a port into a single DNS entry, with priority and weight values that give you failover and load sharing. It lets clients find a service from nothing more than a domain name, which is why VoIP, XMPP, Active Directory, CalDAV, Minecraft and MongoDB all rely on it.
The catch is that SRV records only work for clients that look them up, so always confirm support before you rely on them. Get the underscore naming right, point targets at real hostnames, and test both the DNS record and the port itself after every change.


