When macOS browsers can’t load websites but `ping`, `ssh`, and `dig` still work
I recently ran into a strange networking issue on macOS while running a custom DNS setup with Tailscale and Pi-hole - aka. my Private Ingress Engine.
The machine clearly had network connectivity:
sshworkedparsecworkedping 1.1.1.1workeddigresolved domains
But both Safari and Firefox could not load any websites.
Not public domains:
youtube.com
Not my private domains either:
private.clooney.io
Even stranger: clearing DNS cache did nothing to fix this but resetting the DNS server in macOS network settings instantly fixed the issue.
After digging deeper, the problem turned out to be a split DNS resolver state corruption on macOS combined with a fairly complex DNS path involving Tailscale and a containerized Pi-hole.
My Setup
See detailed explainer in my Private Ingress Engine post
My machines run inside a Tailscale tailnet and use custom DNS.
The MacBook Air points to Tailscale MagicDNS:
DNS server: 100.100.100.100
Architecture:
MacBook Air
↓
100.100.100.100 (Tailscale MagicDNS)
↓
Pi-hole DNS server
↓
Upstream resolvers
The Pi-hole instance itself runs in a container on another machine:
MacBook Pro
└─ Docker container
└─ Pi-hole
└─ connected to a Tailscale container (service mode)
So DNS resolution actually travels through multiple layers:
MacBook Air
→ Tailscale MagicDNS proxy
→ tailnet tunnel
→ MacBook Pro
→ Docker container network
→ Pi-hole
→ upstream DNS
In other words, a DNS request involves two Tailscale hops and a container network boundary.
The Symptoms
When the issue occurred, the system behaved like this:
| Tool | Result |
|---|---|
ping 1.1.1.1 |
✅ works |
ssh server |
✅ works |
dig google.com |
✅ works |
dns-sd -G v4 google.com |
❌ fails |
| Safari | ❌ fails |
| Firefox | ❌ fails |
| private domains | ❌ fails |
So clearly:
- the network stack worked
- DNS servers were reachable
- yet browsers couldn't resolve domains
The Key Detail: macOS Has Two DNS Paths
The confusing part is that dig worked:
dig google.com
This happens because macOS effectively has two different DNS resolution paths.
1. System resolver
Used by many CLI tools.
Handled by:
mDNSResponder
Tools that often use this path:
pingdigssh- various system utilities
2. Network.framework resolver
Used by higher-level networking APIs such as:
URLSession
Network.framework
Browsers rely heavily on this path.
This resolver performs additional validation such as:
- checking DNS server responsiveness
- retry logic
- DNS-over-TCP fallback
- stricter error handling
Browsers therefore tend to be less tolerant of partial DNS failures.
What Was Actually Happening
The machine ended up in a partially broken DNS state.
System resolver (mDNSResponder) → still working
Network.framework resolver → stuck / unhealthy
Which resulted in behavior like:
| Tool | Result |
|---|---|
dig |
works |
ping |
works |
ssh |
works |
dns-sd |
fails |
| browsers | fail |
This explains why the machine appeared healthy while browsers were broken.
Why This Happens with Tailscale + Pi-hole
The DNS path in this setup is fairly long:
Air
↓
Tailscale MagicDNS proxy
↓
tunnel
↓
MacBook Pro
↓
Docker network
↓
Pi-hole
If any of these components briefly hiccup, such as:
- the MacBook Pro sleeping
- a container restart
- Docker network changes
- Pi-hole overload
- Tailscale reconnect
the MagicDNS proxy on the Air can end up in a degraded state.
In that state:
- some queries still succeed
- but certain responses may be malformed, truncated, or delayed
Possible failure modes include:
- truncated DNS responses
SERVFAILresponses- DNS-over-TCP fallback failing
- temporary upstream unavailability
CLI tools often tolerate these issues.
Browsers typically do not.
Why Resetting DNS Fixes It
Toggling the DNS settings forces macOS to rebuild its resolver configuration.
This resets internal state for:
Network.framework
mDNSResponder
per-interface DNS resolvers
Importantly, this is not the same as clearing DNS cache.
Why Clearing DNS Cache Didn't Help
Typical advice suggests running:
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
This clears cached DNS records.
But in this case the problem was the connection state to the resolver, not cached records.
Quick Script to Reset macOS DNS State
Manually toggling DNS settings in System Settings gets old quickly.
Since the fix involves forcing macOS to rebuild its resolver configuration, this can be automated with a small script.
The idea:
- Clear DNS servers and search domains
- Wait briefly so macOS emits a
configdevent - Restore the DNS configuration
Example script:
#!/bin/bash
# Primary network interface (usually en0 on MacBook Air Wi-Fi)
IFACE="en0"
# Grab current Tailscale DNS settings
CURRENT_DNS=$(networksetup -getdnsservers "$IFACE")
CURRENT_SEARCH=$(networksetup -getsearchdomains "$IFACE")
# Clear DNS + search domains (forces configd update)
networksetup -setdnsservers "$IFACE" empty
networksetup -setsearchdomains "$IFACE" empty
sleep 1
# Restore DNS configuration
networksetup -setdnsservers "$IFACE" 100.100.100.100
networksetup -setsearchdomains "$IFACE" your.tailnet.name.ts.net
Running this script effectively performs the same action as toggling DNS settings in the macOS Network UI.
Because it triggers two configd events:
clear DNS → configd rebuild
restore DNS → clean resolver initialization
This resets resolver state used by both:
mDNSResponder
Network.framework
Which is why browsers immediately start resolving domains again.
Optional: Clear DNS Cache
If you also want to clear cached records:
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
sudo killall mDNSResponderHelper
In practice, the resolver reset alone is usually sufficient.
Useful Debugging Commands
If the issue occurs again, these commands help diagnose it before resetting.
Check connectivity:
ping 1.1.1.1
Check DNS directly:
dig @100.100.100.100 google.com
Check the macOS resolver:
dscacheutil -q host -a name google.com
Inspect resolver configuration:
scutil --dns
Test the browser-style resolver path:
dns-sd -G v4 google.com
Likely Root Cause
The most likely sequence looks something like this:
MacBook Air sleeps
↓
Tailscale reconnects
↓
Pi-hole container briefly unavailable
↓
MagicDNS proxy enters degraded state
↓
Network.framework resolver rejects responses
↓
Browsers fail DNS lookups
Resetting DNS forces macOS to rebuild the resolver configuration.
Takeaway
If you encounter a situation where:
- browsers cannot load websites
pingworkssshworksdigworks
the issue may be macOS resolver state corruption, not network connectivity.
This edge case is especially likely when running custom DNS setups involving:
- Tailscale
- Pi-hole
- containerized DNS servers
- private domains
Resetting DNS configuration or cycling the network interface typically resolves the issue.