A fast, dependency-light DNS lookup service β 10 record types, 9 public resolvers, one unified JSON response.
Built in Go. Concurrent by design. Ships with native Prometheus metrics, per-IP token bucket rate limiting, and an embedded modern Web UI out of the box.
Live Demo Β· API Example Β· Report a Bug
DNS Lookup API is a self-hostable, zero-runtime-dependency HTTP microservice that queries A, AAAA, NS, MX, TXT, CNAME, SOA, SRV, CAA, and reverse PTR records against 9 independent public DNS resolvers (Cloudflare, Google, Quad9, OpenDNS, and more).
Instead of parsing raw dig output or dealing with custom low-level sockets, your applications receive a clean, deterministic, and typed JSON response.
- β‘ Concurrent Resolution: Queries all record types concurrently using goroutines. Complete lookups finish in the time of the slowest single record type.
- π Automatic Reverse Lookups: Passing an IPv4 or IPv6 address automatically triggers an
in-addr.arpa/ip6.arpaPTR resolution. - π‘οΈ Built-in Abuse Protection: Per-IP token-bucket rate limiter with automatic stale-client eviction and memory leak protection.
- π Observability Ready: Native Prometheus histograms, counters, and worker gauges exposed under
/metrics. - π¦ Single Static Binary: UI assets are embedded directly into the Go binary (
//go:embed). No external assets or node engines needed.
Prerequisites: Go 1.22 or newer.
# Clone repository
git clone https://github.com/ufukart/DNS-Lookup-API.git
cd DNS-Lookup-API
# Build binary
go build -ldflags="-s -w" -o dns-lookup-api .
# Run (listens on :3000 by default)
./dns-lookup-apiThe Web UI will be available at http://localhost:3000/ and the API at http://localhost:3000/api/lookup.
# Dockerfile
FROM golang:1.24-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o dns-api .
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /root/
COPY --from=builder /app/dns-api .
EXPOSE 3000
CMD ["./dns-api"]# Build & run container
docker build -t dns-lookup-api .
docker run -d -p 3000:3000 --name dns-api dns-lookup-apiThe service is configured entirely via environment variables:
| Variable | Description | Default |
|---|---|---|
PORT |
TCP port the server listens on | 3000 |
TRUSTED_PROXIES |
Comma-separated list of trusted upstream proxy IPs (e.g. 127.0.0.1, 10.0.0.1) allowed to provide X-Forwarded-For and X-Real-IP headers |
(empty) |
π Security Notice: If running behind Cloudflare, Nginx, Traefik, or Caddy, always define
TRUSTED_PROXIESto prevent clients from spoofing their IP address to bypass rate limits.
Performs DNS resolution for a domain or IP address.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
domain |
string |
Yes | β | Fully qualified domain name (example.com), subdomains (_dmarc.domain.com), or IP address (1.1.1.1). |
resolver |
string |
No | cloudflare |
Selected upstream DNS resolver (see Supported Resolvers). |
200 OKβ Lookup executed (individual record errors, if any, will appear in theerrorsarray).400 Bad Requestβ Missing or invalid domain/IP format.405 Method Not Allowedβ HTTP method was notGETorOPTIONS.429 Too Many Requestsβ Client exceeded the rate limit.
curl -s "http://localhost:3000/api/lookup?domain=example.com&resolver=cloudflare"{
"domain": "example.com",
"a": [
{ "ip": "93.184.216.34", "ttl": 300 }
],
"aaaa": [
{ "ip": "2606:2800:220:1:248:1893:25c8:1946", "ttl": 300 }
],
"ns": [
{ "host": "a.iana-servers.net", "ip": "199.43.135.53", "ttl": 172800 },
{ "host": "b.iana-servers.net", "ip": "199.43.133.53", "ttl": 172800 }
],
"mx": [
{ "host": "mail.example.com", "preference": 10, "ip": "93.184.216.35", "ttl": 300 }
],
"txt": [
{ "value": "v=spf1 -all", "ttl": 300 }
],
"soa": {
"ns": "a.iana-servers.net",
"mbox": "noc.dns.icann.org",
"serial": 2024010101,
"refresh": 7200,
"retry": 3600,
"expire": 1209600,
"min_ttl": 3600,
"ttl": 3600
},
"resolver": "1.1.1.1",
"lookup_time_ms": 38,
"timestamp": "2026-03-30T10:15:30Z"
}curl -s "http://localhost:3000/api/lookup?domain=8.8.8.8&resolver=google"{
"domain": "8.8.8.8",
"ptr": [
{ "value": "dns.google", "ttl": 21600 }
],
"resolver": "8.8.8.8",
"lookup_time_ms": 14,
"timestamp": "2026-03-30T10:15:35Z"
}Health-check endpoint for load balancers and orchestrators (e.g. Kubernetes readiness probes).
{
"status": "healthy"
}Prometheus-compatible endpoint exposing runtime and DNS query metrics.
| Type | Name | Output Details |
|---|---|---|
A |
IPv4 Address | List of resolved IPv4 addresses and TTLs |
AAAA |
IPv6 Address | List of resolved IPv6 addresses and TTLs |
NS |
Name Server | Authoritative nameservers with recursive A glue lookup |
MX |
Mail Exchange | Mail servers with priority (preference), glue IP, and TTL |
TXT |
Text Records | Verification records, SPF strings, DKIM entries |
CNAME |
Canonical Name | Target alias and TTL |
SOA |
Start of Authority | Primary NS, administrative email (mbox), serial, timings |
SRV |
Service Locator | Target host, port, priority, weight, and TTL |
CAA |
CA Authorization | Tag, value (e.g. issue, iodef), flags, and TTL |
PTR |
Pointer (Reverse) | Resolved host for IPv4 (in-addr.arpa) and IPv6 (ip6.arpa) |
| Provider | Key | Upstream IP |
|---|---|---|
| Cloudflare (Default) | cloudflare |
1.1.1.1 |
| Google Public DNS | google |
8.8.8.8 |
| Quad9 | quad9 |
9.9.9.9 |
| OpenDNS | opendns |
208.67.222.222 |
| AdGuard DNS | adguard |
94.140.14.14 |
| DNS.WATCH | dnswatch |
84.200.69.80 |
| Comodo Secure DNS | comodo |
8.26.56.26 |
| CleanBrowsing | cleanbrowsing |
185.228.168.9 |
| UltraDNS | ultradns |
64.6.64.6 |
- Token Bucket Algorithm: Configured by default for 5 requests per second per client IP with a burst allowance of 10 requests.
- Memory Safety: Rate limiter tracking structures automatically clean up idle IPs after 1 hour using concurrent background routines.
- Global Concurrency Semaphore: Prevents socket and file-descriptor exhaustion by limiting concurrent upstream lookups to 1,000 simultaneously.
- Timeout Guarantees: 2-second timeout per DNS query and a 6-second global request deadline.
The /metrics endpoint exposes key operational metrics:
| Metric | Type | Labels | Description |
|---|---|---|---|
dns_api_request_duration_seconds |
Histogram | status, resolver |
End-to-end API HTTP request latency. |
dns_query_duration_seconds |
Histogram | rtype, resolver, transport |
Upstream DNS query latency per record type and transport (udp/tcp). |
dns_api_requests_total |
Counter | status |
Total count of API requests by status code or rate_limited. |
dns_api_active_workers |
Gauge | β | Number of currently running DNS resolution workers. |
- In-memory LRU / Redis cache for repeated queries
- API key authentication middleware
- DNS over HTTPS (DoH) / DNS over TLS (DoT) upstream query options
- JSON Schema validation endpoints
Contributions are very welcome!
- Fork the project.
- Create your feature branch (
git checkout -b feature/amazing-feature). - Commit your changes (
git commit -m 'feat: add amazing feature'). - Push to the branch (
git push origin feature/amazing-feature). - Open a Pull Request.
This project is licensed under the MIT License β see the LICENSE file for details.
If this project helps you in your workflow, consider supporting its development.
