Fast, API-first DNS toolkit. No accounts, no API keys, no tracking.
Base URL: https://ns.lol · JSON endpoint: /api/docs
curl -s https://ns.lol/example.com | jq
curl -s https://ns.lol/example.com | jq
a aaaa cname mx txt ns soa srv caa https ds ptr dnskey naptr tlsa sshfp loc hinfocurl -s https://ns.lol/example.com/mx | jq
curl -s https://ns.lol/example.com/65 | jq # HTTPS record
curl -s https://ns.lol/example.com/any | jq
curl -s https://ns.lol/example.com/trace | jq
curl -s https://ns.lol/8.8.8.8 | jq
curl -s https://ns.lol/2606:4700:4700::1111 | jq
curl -s "https://ns.lol/example.com/propagation?type=MX" | jq
| Param | Description |
|---|---|
?type= | Record type to check (default: A) |
?expected= | Expected value — resolvers flagged as matching or divergent |
curl -s https://ns.lol/example.com/health | jq
curl -s https://ns.lol/example.com/email | jq
curl -s https://ns.lol/example.com/security | jq
curl -s -X POST https://ns.lol/batch \
-H 'Content-Type: application/json' \
-d '{"domains":["google.com","github.com"],"type":"A"}' | jq
curl -s https://ns.lol/api/docs | jq
| Parameter | Type | Description |
|---|---|---|
?explain=true | boolean | Add plain-English explanations to every record and signal. Bypasses cache. |
?force=true | boolean | Bypass cache and force a fresh lookup. |
?expected= | string | Expected DNS value for propagation — resolvers flagged as matching or divergent. |
?type= | string | Record type for propagation checks (default: A). |
| Accept Header | Response |
|---|---|
application/json | JSON (default for curl, httpie, wget) |
application/dns-json | Alias for JSON (RFC 8484) |
text/plain | dig-style plain text output |
text/html | Interactive SPA (default for browsers) |
120 requests per hour per IP, enforced via Cloudflare Durable Objects with a rolling window. DNS lookups are lightweight, so ns.lol allows more requests than certs.lol (60/hr) where each scan involves a TLS probe.
Rate limits exist for abuse prevention — they keep hosting costs near zero so ns.lol can stay free. Cached results still count toward the limit.
Every response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Max requests per window (120) |
X-RateLimit-Remaining | Requests remaining |
X-RateLimit-Reset | Unix timestamp when window resets |
X-Cache | HIT or MISS — whether result came from cache |
When exceeded, returns 429 with Retry-After header.
Not rate-limited: /, /health, /docs, /api/docs, /about, /privacy, /terms.
Need unlimited lookups? Install the CLI — same engine, runs locally, no rate limits.
| Endpoint | Cache TTL |
|---|---|
| Record lookups, full reports | 1 hour |
| Health, security checks | 6 hours |
| Propagation | Never — always live |
Bypass with ?force=true or ?explain=true. The X-Cache response header shows HIT or MISS. The _meta.cache_hit field in JSON responses also indicates cache status.
# Full DNS report
curl -s https://ns.lol/example.com | jq
# Single record type
curl -s https://ns.lol/example.com/mx | jq
# Reverse DNS
curl -s https://ns.lol/8.8.8.8 | jq
# Propagation with expected value
curl -s "https://ns.lol/example.com/propagation?expected=93.184.216.34" | jq
# Zone health with explanations
curl -s "https://ns.lol/example.com/health?explain=true" | jq
# Email DNS audit
curl -s https://ns.lol/example.com/email | jq
# Security analysis
curl -s https://ns.lol/example.com/security | jq
# Authority trace
curl -s https://ns.lol/example.com/trace | jq
# dig-style output
curl -sH "Accept: text/plain" https://ns.lol/example.com
# Batch lookup
curl -s -X POST https://ns.lol/batch \
-H 'Content-Type: application/json' \
-d '{"domains":["google.com","github.com"]}' | jq
# Check rate limit headers
curl -si https://ns.lol/example.com 2>&1 | grep X-RateLimit