Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Automation By James Joyner IV · · 7 min read

curl Error: '(6) Could not resolve host' — Cause, Fix, and Troubleshooting Guide

Quick answer

Fix curl: (6) Could not resolve host: api.example.com — DNS resolution failures from typos, broken resolv.conf, VPN/split-horizon names, and container DNS.

  • #automation
  • #troubleshooting
  • #curl
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

curl exit code 6 is a name-resolution failure: curl asked the resolver to turn a hostname into an IP address and got nothing back. It never opened a socket — this happens before any TCP connection, so it is purely a DNS problem, not a firewall or service problem.

$ curl -v https://api.example.com/health
* Could not resolve host: api.example.com
* Closing connection
curl: (6) Could not resolve host: api.example.com

The distinction matters for triage: code 6 means “I don’t know where that name points,” which is different from code 7 (“I know the address but can’t connect”) and code 28 (“I tried but timed out”). The fix lives in DNS configuration, /etc/hosts, the resolver, or the name itself — never in the target service.

Symptoms

  • curl exits with curl: (6) Could not resolve host: <name>.
  • The failure is near-instant, with no Trying <ip>... line — because curl never got an IP to try.
  • getent hosts <name> returns nothing.
  • Resolving by IP works but resolving by name fails.
  • The name resolves on your laptop but not inside a container, CI runner, or a host off the VPN.
curl -sS -o /dev/null -w '%{http_code}\n' https://api.example.com/health; echo "exit: $?"
exit: 6

Common Root Causes

1. Typo in the hostname

The simplest and most common: api.exmaple.com, a trailing space, or a copy-paste that dropped a character.

2. No working DNS / broken resolv.conf

The resolver is empty, points at an unreachable server, or was overwritten.

cat /etc/resolv.conf
# (empty)

3. Internal name that only resolves on the VPN or inside the cluster

Split-horizon DNS: api.internal.example.com resolves on the corporate network or inside Kubernetes, but not from a public host or a disconnected VPN.

4. Missing /etc/hosts entry for a name that has no DNS record

A name that is only defined in /etc/hosts (or was expected to be) fails everywhere the entry is absent.

5. Container / pod DNS misconfiguration

A container with the wrong --dns, a broken resolv.conf mounted from the host, or CoreDNS not reachable from the pod.

6. Proxy expected to do resolution

In some corporate setups the name only resolves through an HTTP proxy; curl bypassing the proxy cannot resolve it directly.

How to Diagnose

Step 1: Confirm it is DNS, isolated from curl

getent hosts api.example.com || echo "no resolution"
no resolution

getent uses the same NSS path as most programs; an empty result confirms a resolver-level failure.

Step 2: Query DNS directly

dig +short api.example.com
nslookup api.example.com
;; connection timed out; no servers could be reached

An empty answer means no record; “no servers could be reached” means the resolver itself is broken.

Step 3: Inspect the resolver configuration

cat /etc/resolv.conf
nameserver 10.0.0.2
search svc.cluster.local

An empty file, a 127.0.0.53 stub with no upstream, or a wrong nameserver all break resolution.

Step 4: Test with a known-good resolver

dig @1.1.1.1 +short api.example.com

If a public resolver answers but your configured one does not, the fault is your resolver, not the record. If neither answers, the record does not exist publicly (likely an internal/VPN name).

Step 5: Check basic network reachability

ping -c1 1.1.1.1

No route to a public IP means the box has no network at all, which also breaks DNS.

Fixes

Correct an obvious typo and retry:

curl -v https://api.example.com/health

Repair the resolver. On a systemd-resolved host:

sudo systemctl restart systemd-resolved
resolvectl status | head

Or set a working nameserver directly (for a host not managed by resolved):

# /etc/resolv.conf
nameserver 10.0.0.2
nameserver 1.1.1.1

For an internal name, connect the VPN or run from inside the cluster; verify with getent hosts. As a temporary override, add an /etc/hosts entry:

echo "10.0.5.40  api.example.com" | sudo tee -a /etc/hosts
getent hosts api.example.com
10.0.5.40       api.example.com

For containers, set a reachable DNS server:

docker run --dns 10.0.0.2 myimage curl -sS https://api.example.com/health

In Kubernetes, confirm CoreDNS is healthy and the pod’s resolv.conf points at the cluster DNS service.

What to Watch Out For

  • Code 6 is strictly DNS — do not open firewall tickets or restart the target service; neither is the cause.
  • search domains in resolv.conf can make a short name resolve while the FQDN fails (or vice-versa); test the exact string curl uses.
  • A stale /etc/hosts override outlives the outage it was meant to patch and later sends traffic to a dead IP — remove temporary entries.
  • Split-horizon names look “broken” from the wrong network but are working as designed; check whether the name is supposed to be internal.
  • Containers inherit DNS from the host or the runtime, not your shell — debug resolution inside the container.
Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.