Fix curl: (6) Could not resolve host When Calling APIs from Terminal or Scripts

beginner🌐 Networking2026-05-17| Linux (Ubuntu, Debian, CentOS, RHEL), macOS, WSL2 β€” curl 7.x and 8.x

Error Message

curl: (6) Could not resolve host: api.example.com
#curl#dns#linux#networking

The Error

You run a curl command β€” maybe in a script, a CI pipeline, or just your terminal β€” and get this:

curl: (6) Could not resolve host: api.example.com

Exit code 6 means DNS resolution failed. curl never found an IP for the hostname, so it never even tried to connect. The server might be perfectly fine. Your machine just can't look it up.

Root Causes

  • DNS server unreachable or misconfigured (/etc/resolv.conf points nowhere)
  • No network connectivity at all (link is down)
  • Typo in the hostname β€” more common in scripts than you'd think
  • VPN or proxy blocking DNS queries
  • Corporate firewall blocks outbound UDP port 53
  • Docker or WSL2 not inheriting DNS from the host
  • Stale or conflicting entry in /etc/hosts

Step 1 β€” Confirm it's DNS, not a dead network

Start with the simplest check:

ping -c 3 8.8.8.8

Three successful pings mean your network link is up. Skip ahead. If all three fail, you have a network problem β€” fix that first, because no DNS trick will save you here.

With the network confirmed alive, test DNS directly:

nslookup api.example.com
# or
dig api.example.com

SERVFAIL or connection timed out from nslookup points to a broken resolver. Move to Step 2. nslookup succeeds but curl still fails? That's an nsswitch.conf edge case β€” jump to Step 4.

Step 2 β€” Check your DNS resolver config

cat /etc/resolv.conf

A healthy file has at least one working nameserver:

nameserver 8.8.8.8
nameserver 1.1.1.1

An empty file, a nameserver 127.0.0.53 that isn't responding, or a private IP that's unreachable β€” any of these will cause exit code 6.

Quick sanity check with an explicit resolver:

curl --dns-servers 8.8.8.8 https://api.example.com

Works now? Your default resolver is the problem. Patch /etc/resolv.conf:

# Temporary override β€” resets on reboot or network restart
sudo bash -c 'echo "nameserver 8.8.8.8" > /etc/resolv.conf'
sudo bash -c 'echo "nameserver 1.1.1.1" >> /etc/resolv.conf'

On Ubuntu with systemd-resolved, the permanent fix is different:

sudo systemctl enable --now systemd-resolved
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

Step 3 β€” Rule out a typo in the hostname

Scripts are brutal for this. An extra dash, a missing dot, a wrong TLD β€” and you get exit code 6 with no obvious clue why.

# Query a known-good public resolver
nslookup api.example.com 8.8.8.8

NXDOMAIN (Non-Existent Domain) from Google's resolver means the hostname doesn't exist. It's not a DNS config issue β€” the domain itself is wrong. Audit your env vars:

echo "$API_BASE_URL"
curl -v "$API_BASE_URL/health"

Pay close attention to double slashes, trailing spaces, or environment variables that weren't set and silently expanded to an empty string.

Step 4 β€” VPN or proxy interfering with DNS

VPNs push their own DNS servers β€” and sometimes that push breaks. Check what's actually resolving your queries:

resolvectl status   # systemd-resolved systems
scutil --dns        # macOS

Disconnect the VPN and rerun curl. Fixed? The VPN's DNS configuration is the culprit. Either adjust split-DNS settings in your VPN client, or loop in your network admin.

Corporate HTTP proxies handle DNS on your behalf, so curl needs to know about them:

# Pass proxy explicitly
curl -x http://proxy.corp.example.com:3128 https://api.example.com

# Or export it for the whole session
export https_proxy=http://proxy.corp.example.com:3128
curl https://api.example.com

Step 5 β€” Fix DNS inside Docker containers

Containers don't automatically inherit your host's DNS. Test first:

docker run --rm alpine nslookup api.example.com

Fails? Pass DNS at runtime:

docker run --rm --dns 8.8.8.8 alpine nslookup api.example.com

For a permanent fix across all containers, edit /etc/docker/daemon.json:

{
  "dns": ["8.8.8.8", "1.1.1.1"]
}
sudo systemctl restart docker

Step 6 β€” Check /etc/hosts for conflicts

grep api.example.com /etc/hosts

A stale entry here overrides DNS entirely. curl will try the hardcoded IP β€” which might be wrong, decommissioned, or pointing to a local dev environment. Remove or correct any outdated lines.

Step 7 β€” Firewall blocking UDP port 53

Some corporate and cloud environments silently drop outbound DNS traffic on UDP 53. Switch to TCP to test:

dig +tcp api.example.com @8.8.8.8

TCP resolves it but plain dig api.example.com hangs? UDP 53 is being filtered. Your options: use DNS-over-HTTPS, or ask the network team to open the port.

Verification β€” Confirm the fix worked

# 1. DNS resolves successfully
nslookup api.example.com
# Expected: one or more Address lines with a real IP

# 2. curl connects
curl -v https://api.example.com/
# Look for: "* Connected to api.example.com (x.x.x.x)"
# Not: "Could not resolve host"

# 3. From a script, check the exit code explicitly
curl -sf https://api.example.com/health && echo "OK" || echo "FAILED: $?"

Prevention Tips

Validate the hostname before handing it to curl:

HOST=$(echo "$API_BASE_URL" | awk -F[/:] '{print $4}')
if ! nslookup "$HOST" > /dev/null 2>&1; then
  echo "ERROR: Cannot resolve $HOST β€” check DNS or the URL" >&2
  exit 1
fi
curl "$API_BASE_URL/data"

Add retry logic for transient DNS blips:

curl --retry 3 --retry-delay 2 --retry-connrefused https://api.example.com

Bypass DNS entirely during local testing with --resolve:

# Pin a specific IP without touching /etc/hosts
curl --resolve api.example.com:443:93.184.216.34 https://api.example.com

When the underlying issue is network routing rather than DNS config β€” say, figuring out which resolver is reachable from a given subnet β€” the IP Subnet Calculator on ToolCraft can help you work out subnets and CIDR ranges without installing anything locally.

Related Error Notes