Setting DNS Server to Use With a Curl Request: Fix

By Published 12 min read Hosting
Setting DNS Server to Use With a Curl Request: Fix

Can you tell curl to use a specific DNS server instead of the one configured on your computer or hosting server? Yes, but the method depends on how curl was built and whether you want to change the DNS resolver or connect to a specific IP address.

If you're setting DNS server to use with a curl request, the direct option is --dns-servers, but it only works when curl uses the c-ares resolver. Other builds can use DNS-over-HTTPS with --doh-url. If you already know the destination IP address, --resolve lets you bypass the normal hostname lookup for that request.

This tutorial covers all three methods, including PHP cURL, so you can choose the right approach without changing the DNS settings of your entire server.

Setting DNS server to use with a curl request in 6 steps

By default, curl uses the DNS resolution mechanism provided by its build and operating environment.

On Linux, this may involve the system resolver configuration, such as /etc/resolv.conf or a resolver service managed by the operating system.

On Windows, DNS resolution normally follows the network's configured resolver settings when curl uses the native resolver.

For example:

curl https://example.com

Before curl can connect to example.com, it generally needs to determine the destination IP address.

The normal request flow looks like this:

curl https://example.com
         |
         v
DNS lookup
         |
         v
System-configured resolver
         |
         v
IP address returned
         |
         v
TCP/TLS connection
         |
         v
HTTPS response

Sometimes the system resolver is unavailable, returns an unexpected address, or cannot resolve an internal hostname.

In those cases, you may want a different DNS resolver for one request rather than modifying the server's network configuration.

Step 1: Confirm whether the problem is DNS resolution

First, reproduce the request using verbose output.

Run:

curl -v https://example.com/

The -v option displays connection details, including hostname resolution and the address curl attempts to contact.

A successful lookup may produce output similar to:

* Host example.com:443 was resolved.
* IPv4: ...
*   Trying ...
* Connected to example.com

The exact messages depend on the installed curl version and network configuration.

If DNS resolution fails, you may see:

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

This is curl error 6, meaning the destination hostname couldn't be resolved.

You can reproduce this type of failure with a deliberately invalid hostname:

curl -v https://missing.example.invalid/

The .invalid domain is reserved for names that should not resolve through public DNS.

If curl is using a proxy, however, the error may concern the proxy instead of the destination.

For example:

curl: (5) Could not resolve proxy

That's a different problem.

What to check before changing DNS:

  • Does the hostname actually exist?
  • Is the DNS server reachable from your machine?
  • Is curl using an HTTP or SOCKS proxy?
  • Does the same hostname resolve through another DNS resolver?

You can compare public DNS responses using:

nslookup example.com 1.1.1.1

This asks Cloudflare's public DNS resolver to look up example.com.

If that succeeds while curl reports a resolution failure, the system resolver or curl's network path deserves closer investigation.

A successful nslookup doesn't automatically mean curl can reach the website. DNS lookup and HTTPS connectivity are separate operations.

Step 2: Use --dns-servers to select a specific DNS resolver

The most direct curl option is:

curl --dns-servers 1.1.1.1 https://example.com/

This tells a compatible curl build to use 1.1.1.1 for DNS resolution instead of the system's default resolver.

You can also provide multiple DNS servers:

curl --dns-servers 1.1.1.1,1.0.0.1 https://example.com/

Or specify a DNS port:

curl --dns-servers 1.1.1.1:53 https://example.com/

Port 53 is the normal port for conventional DNS queries.

The limitation is that --dns-servers requires curl to be built with c-ares support.

It isn't available in every curl installation.

Check whether curl supports c-ares

Run:

curl -V

Look at the version information.

A c-ares-enabled build typically identifies c-ares in its version or resolver information.

Don't assume the presence of AsynchDNS in the features list proves c-ares support. Curl can also perform asynchronous DNS resolution using other backends.

If your build doesn't support the option, trying --dns-servers may return an error indicating that the installed libcurl doesn't support it.

The complete option requirements are documented in the official curl DNS server documentation.

On Windows PowerShell, explicitly use:

curl.exe -V

Using curl.exe avoids confusion with the curl alias found in some Windows PowerShell environments.

What to expect: If your curl build supports c-ares and the DNS server is reachable, curl resolves example.com through the requested resolver and proceeds with the HTTPS connection.

If your curl build doesn't support c-ares, move to the next step instead of repeatedly changing DNS addresses.

Step 3: Use DNS-over-HTTPS when --dns-servers isn't supported

A practical alternative is DNS-over-HTTPS, usually called DoH.

Instead of sending conventional DNS queries to a resolver over port 53, curl sends DNS queries through an HTTPS endpoint.

Curl provides the following option:

curl --doh-url https://cloudflare-dns.com/dns-query https://example.com/

The URL:

https://cloudflare-dns.com/dns-query

is Cloudflare's documented DNS-over-HTTPS endpoint.

This instructs curl to use that DoH service when resolving the destination hostname.

For troubleshooting, add verbose output:

curl -v \
  --doh-url https://cloudflare-dns.com/dns-query \
  https://example.com/

The backslashes shown above are line continuations for Unix-like shells. If you're using Windows PowerShell, put the command on one line:

curl.exe -v --doh-url https://cloudflare-dns.com/dns-query https://example.com/

Your curl installation must support the --doh-url option and the required HTTPS functionality.

What if curl cannot resolve the DoH server itself?

There's a detail that often gets missed.

Before curl can ask cloudflare-dns.com to resolve example.com, it must first connect to the DoH service.

If the configured DoH service uses a hostname, its initial hostname lookup normally uses the regular resolver.

That creates a bootstrap problem when your system DNS is completely unavailable.

You can supply the DoH server's known IP address:

curl -v \
  --resolve cloudflare-dns.com:443:1.1.1.1 \
  --doh-url https://cloudflare-dns.com/dns-query \
  https://example.com/

Here, 1.1.1.1 is a documented Cloudflare resolver address.

The --resolve option provides the address for the DoH hostname, while --doh-url tells curl where to perform the destination hostname lookup.

This is useful when conventional DNS is broken but HTTPS connectivity to the DoH service is available.

Important: Don't disable TLS certificate verification to make DNS troubleshooting easier. A certificate failure is a separate issue and should be investigated rather than bypassed.

Step 4: Use --resolve to connect to a specific IP address

Sometimes you don't actually need to select another DNS server.

You already know the destination IP address and simply want curl to connect there.

For that situation, use:

--resolve hostname:port:ip-address

For example, to test the known Cloudflare DoH hostname at its documented resolver address:

curl -v \
  --resolve cloudflare-dns.com:443:1.1.1.1 \
  https://cloudflare-dns.com/dns-query

The DoH endpoint may return an HTTP error because this request doesn't contain a DNS query. That's fine for this particular connection test. Look for successful connection and TLS verification in the verbose output.

The significant part is:

--resolve cloudflare-dns.com:443:1.1.1.1

Curl uses the specified IP address for that hostname and port.

This differs from --dns-servers.

The --dns-servers option selects a resolver to answer DNS queries.

The --resolve option supplies an address directly, avoiding the usual DNS lookup for that hostname and port.

Why --resolve is better than changing the Host header

You might be tempted to connect to an IP address and manually set the HTTP Host header.

For HTTPS, that isn't always sufficient.

TLS uses the requested hostname for server name indication and certificate verification.

Keeping the original hostname in the URL while overriding the connection address is the cleaner approach.

It's especially useful when:

  • Testing a website before DNS records are updated.
  • Checking a new hosting server.
  • Comparing responses from two web servers.
  • Investigating whether a DNS record points to the wrong address.

For another example of separating connection problems from protocol errors, see our guide to fixing curl error 35 and SSL wrong version number on Nginx.

One warning: --resolve isn't a general-purpose replacement for DNS.

It only applies to the hostname and port you specify. Other hostnames, including those used during redirects, may still need normal resolution.

Step 5: Set a custom DNS server in PHP cURL

If you're running PHP on a hosting server, you may want the same behavior inside a PHP script.

PHP's cURL extension exposes several libcurl options, including CURLOPT_DNS_SERVERS when the installed PHP/libcurl combination supports it.

Create a file named:

dns-test.php

Add:

<?php

$url = 'https://example.com/';

$ch = curl_init($url);

if ($ch === false) {
    throw new RuntimeException(
        'Unable to initialize cURL.'
    );
}

if (!defined('CURLOPT_DNS_SERVERS')) {
    curl_close($ch);

    throw new RuntimeException(
        'CURLOPT_DNS_SERVERS is not available.'
    );
}

$dnsConfigured = curl_setopt(
    $ch,
    CURLOPT_DNS_SERVERS,
    '1.1.1.1'
);

if (!$dnsConfigured) {
    curl_close($ch);

    throw new RuntimeException(
        'This libcurl build cannot set custom DNS servers.'
    );
}

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT => 30,
]);

$response = curl_exec($ch);

if ($response === false) {
    echo 'cURL Error: ' . curl_error($ch);
} else {
    echo 'HTTP Status: ' .
        curl_getinfo($ch, CURLINFO_HTTP_CODE);
}

curl_close($ch);

Run:

php dns-test.php

This example only works when your PHP cURL extension and underlying libcurl library support the DNS server option.

The PHP constant being defined doesn't guarantee that libcurl was built with c-ares.

A failed curl_setopt() call can also produce a PHP warning, depending on the installed extension.

Check the return value rather than assuming the DNS option was applied.

Alternative: Use CURLOPT_RESOLVE in PHP

When you know a hostname's IP address, you can use CURLOPT_RESOLVE instead.

Here's a complete connection test:

<?php

$ch = curl_init('https://cloudflare-dns.com/dns-query');

curl_setopt_array($ch, [
    CURLOPT_RESOLVE => [
        'cloudflare-dns.com:443:1.1.1.1',
    ],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT => 30,
]);

$response = curl_exec($ch);

if ($response === false) {
    echo 'Error: ' . curl_error($ch);
} else {
    echo 'Connected successfully. HTTP status: ' .
        curl_getinfo($ch, CURLINFO_HTTP_CODE);
}

curl_close($ch);

Again, a non-200 HTTP status from this DNS service is possible because we're testing connectivity without submitting a DNS question.

For an ordinary application endpoint, replace the URL and resolve entry with the actual destination hostname and verified IP address.

This method doesn't require the c-ares DNS resolver backend.

For Laravel developers, the underlying database host concept is similar: the hostname determines where a connection should go. Our explanation of host values in MySQL connections covers that distinction in more detail.

Step 6: Check proxies, DNS caches, and server configuration

If custom DNS settings appear to make no difference, check whether curl is actually resolving the target hostname locally.

Check for a proxy

Run:

curl -v https://example.com/

Look for verbose messages showing proxy environment variables or a proxy connection.

For a direct-connect comparison, run:

curl -v --noproxy '*' https://example.com/

The --noproxy '*' option disables proxy use for the request.

If an HTTP proxy resolves the destination hostname itself, changing curl's local DNS resolver may not affect that destination lookup.

SOCKS proxies can behave differently depending on the selected protocol.

For example:

socks5://

typically means the client resolves the destination hostname locally.

But:

socks5h://

requests hostname resolution through the SOCKS proxy.

That difference matters when troubleshooting DNS.

Check the operating system resolver

On Linux systems using systemd-resolved, try:

resolvectl status

You can also inspect:

cat /etc/resolv.conf

On Windows PowerShell:

Get-DnsClientServerAddress

These commands help identify the resolver settings associated with the operating system.

Don't immediately edit /etc/resolv.conf on a managed server. NetworkManager, systemd-resolved, a container runtime, or hosting management software may regenerate it.

Changing the server's DNS configuration can affect other applications.

For a one-request test, I would use --doh-url or --resolve before modifying system-wide DNS settings.

Check whether DNS caching is involved

Curl can cache resolved addresses during a running libcurl session.

For short command-line tests, starting a new curl process is a simple way to avoid reusing that process's existing DNS cache.

Long-running PHP applications may reuse handles or connection pools, so cached resolution can become relevant there.

Also remember that web servers and reverse proxies can have their own DNS behavior.

Changing curl's resolver doesn't update a domain's authoritative DNS records, and it doesn't guarantee that every other application on the server will use the same resolver.

Verify that curl is using the intended DNS method

After applying your chosen method, run a verbose request again.

For a compatible c-ares build:

curl -v \
  --dns-servers 1.1.1.1 \
  https://example.com/

For DNS-over-HTTPS:

curl -v \
  --doh-url https://cloudflare-dns.com/dns-query \
  https://example.com/

For the DoH service with a fixed bootstrap address:

curl -v \
  --resolve cloudflare-dns.com:443:1.1.1.1 \
  --doh-url https://cloudflare-dns.com/dns-query \
  https://example.com/

Look for successful name resolution, the intended connection address, a completed TLS handshake, and an HTTP response.

A successful HTTP request confirms that the connection worked. It doesn't, by itself, prove which DNS server answered the lookup.

For that, use curl's resolver debug output where supported or inspect DNS traffic on the machine. With DoH, the DNS exchange is encrypted, so packet inspection won't expose the DNS question without additional instrumentation.

You can also try an alternate DNS service to compare results.

Keep in mind that public resolvers may return different answers because of DNS caching, geographic routing, or domain-specific policies.

FAQ

Can I specify a DNS server directly in a curl command?

Yes, if curl was built with c-ares support.

For example:

curl --dns-servers 1.1.1.1 https://example.com/

If your installed curl doesn't support that option, use a supported DNS-over-HTTPS endpoint with --doh-url or supply a known destination address with --resolve.

Why does curl say "Could not resolve host" even though the website works in my browser?

The browser and curl may use different DNS mechanisms, cached records, or proxy settings.

Some browsers can use their own DNS-over-HTTPS configuration, while curl may rely on the operating system resolver.

Use curl -v and compare the results with nslookup to identify where hostname resolution is failing.

Does CURLOPT_DNS_SERVERS work on every PHP hosting server?

No. The option depends on the libcurl library that PHP uses, and selecting custom conventional DNS servers requires the c-ares resolver backend.

Some shared hosting environments don't provide that capability.

If it isn't available, consider a supported DoH option, CURLOPT_RESOLVE for a known address, or an approved server-level DNS change.

What's the difference between --dns-servers and --resolve in curl?

--dns-servers tells curl which DNS server should resolve hostnames.

--resolve provides a specific IP address for a hostname and port, bypassing the normal DNS lookup for that entry.

Use --dns-servers when you want an alternate resolver. Use --resolve when you already know the destination address and need to test that specific server.

Can I use Google or Cloudflare DNS without changing my server settings?

Yes, provided your curl build and network environment support the chosen method.

For Cloudflare, a compatible c-ares build can use --dns-servers 1.1.1.1. Alternatively, a DoH-capable build can use Cloudflare's HTTPS DNS endpoint.

For Google's public DNS service, the conventional resolver addresses include 8.8.8.8 and 8.8.4.4. Select a resolver that your network policy permits and that supports your application's requirements.

If you need help diagnosing a hosting-specific DNS or PHP cURL configuration, contact HeadsNTail with the curl version information and the relevant error output.

The next step after setting dns server to use with a curl request is to test the same URL with both your default resolver and the selected alternative, then keep the smallest configuration change that fixes the actual problem.

Free tools for Hosting work

All free tools →

More Hosting articles