DoH Wire Format (RFC 8484)
Send application-scoped ResolveDB DNS queries over HTTPS using RFC 8484 wire format.
Endpoint
https://doh.resolvedb.io/dns-queryResolveDB is authoritative-only. Use this endpoint for ResolveDB qnames; do not configure it as a browser or operating-system resolver for unrelated domains.
GET
Build a DNS message, encode it as unpadded Base64url, and send it in the dns
query parameter:
GET /dns-query?dns={base64url-dns-message}
Accept: application/dns-messageThe encoded parameter is limited to 8 KiB and the decoded DNS message is limited to 4 KiB. Generate the bytes with a DNS library rather than hand-encoding names.
POST
Send a DNS wire message as the request body:
POST /dns-query
Content-Type: application/dns-message
Accept: application/dns-message
{binary DNS message}The request body is limited to 4 KiB.
Python Example
import dns.message
import dns.query
query = dns.message.make_query(
"get.newyork.weather.public.v1.resolvedb.net",
"TXT",
)
response = dns.query.https(
query,
"https://doh.resolvedb.io/dns-query",
)
for rrset in response.answer:
for record in rrset:
print(record.to_text())Go Example
package main
import (
"encoding/base64"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"github.com/miekg/dns"
)
func main() {
message := new(dns.Msg)
message.SetQuestion("get.newyork.weather.public.v1.resolvedb.net.", dns.TypeTXT)
wire, err := message.Pack()
if err != nil {
panic(err)
}
encoded := base64.RawURLEncoding.EncodeToString(wire)
endpoint := "https://doh.resolvedb.io/dns-query?dns=" + url.QueryEscape(encoded)
request, err := http.NewRequest(http.MethodGet, endpoint, nil)
if err != nil {
panic(err)
}
request.Header.Set("Accept", "application/dns-message")
response, err := http.DefaultClient.Do(request)
if err != nil {
panic(err)
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil {
panic(err)
}
answer := new(dns.Msg)
if err := answer.Unpack(body); err != nil {
panic(err)
}
for _, rr := range answer.Answer {
if txt, ok := rr.(*dns.TXT); ok {
fmt.Println(strings.Join(txt.Txt, ""))
}
}
}Responses
Successful HTTP handling returns application/dns-message; inspect the DNS
RCODE for query-level failures.
| RCODE | Meaning |
|---|---|
NOERROR | Answer or NODATA |
FORMERR | Malformed UQRP input |
SERVFAIL | Service or storage failure |
REFUSED | Authorization, namespace, or reserved-resource denial |
Wire responses with answers use Cache-Control: max-age=<minimum DNS TTL>.
Errors, empty answers, and private TTL-0 answers use Cache-Control: no-store.
TXT records may contain multiple 255-byte character strings; concatenate them in
order before parsing the UQRP envelope.
HTTP Errors
| Status | Meaning |
|---|---|
200 | DNS response returned; inspect its RCODE |
400 | Missing, malformed, or oversized DNS message |
406 | Accept does not allow application/dns-message |
415 | POST body has the wrong media type |