CURLOPT_RESOLVE(3)
β¨ CURLOPT_RESOLVE: your personal DNS plug π
Hey bestie, welcome to the CURLOPT_RESOLVE page from the libcurl manual (Library Functions Manual, if we're being formal π). This one's lowkey iconic: it's how you tell curl "hey, when you see this hostname on this port, use this IP address, mmkay?" No actual DNS lookup needed. It's giving main character energy for your DNS cache fr fr.
πΈ NAME πΈ
CURLOPT_RESOLVE β provide custom hostname to IP address resolves π¦
β¨ SYNOPSIS β¨
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESOLVE,
struct curl_slist *hosts);
π DESCRIPTION π
Okay so bestie, here's the tea β: you pass a pointer to a linked list of strings stuffed with hostname resolve info, and libcurl uses those for requests made with this handle. That linked list needs to be a fully valid list of struct curl_slist structs, properly filled in, no cap. Use curl_slist_append(3) to build the list and curl_slist_free_all(3) to clean up the whole entire thing afterwards. π«Ά
And listen β libcurl does not copy the list. It needs to be kept around until after the transfer has completed. Do not free it early, that's a no β.
Each resolve rule you add should be written using the format:
[+]HOST:PORT:ADDRESS[,ADDRESS]
Where HOST is the name libcurl wants to resolve, PORT is the port number of the service where libcurl wants to connect to the HOST, and ADDRESS is one or more numerical IP addresses. If you specify multiple IP addresses they need to be separated by comma. And if libcurl is built to support IPv6, each of the ADDRESS entries can of course be either IPv4 or IPv6 style addressing. Versatile queen π
You can also specify the host as a single asterisk (*) to match all names π. This wildcard is resolved last, so any resolve with a specific host and port number is given priority. Priorities, we love them.
This option effectively populates the DNS cache with entries for the host+port pair, so redirects and everything that operates against the HOST+PORT use your provided ADDRESS instead. It's literally a fake-it-till-you-make-it DNS situation and I'm obsessed. π₯
The optional leading plus (+) specifies that the new entry should timeout. Entries added without the leading plus character never times out, whereas entries added with +HOST:... times out just like ordinary DNS cache entries. Permanent girlies vs. temporary girlies, choose your fighter π
If the DNS cache already has an entry for the given host+port pair, the new entry overrides the former one. New info wins, periodt.
An ADDRESS provided by this option is only used if not restricted by the setting of CURLOPT_IPRESOLVE(3) to a different IP version. So check that vibe first, bestie, or your cute little address won't even get used. π
To remove names from the DNS cache again β to stop providing these fake resolves β include a string in the linked list that uses the format:
-HOST:PORT
The entry to remove must be prefixed with a dash, and the hostname and port number must exactly match what was added previously. Exact match only, no fuzzy vibes, no exceptions. π
Provide IPv6 addresses within [brackets]. Brackets are not optional here, they're the whole look π
Using this option multiple times makes the last set list override the previous ones. Set it to NULL to disable its use again.
π₯ DEFAULT π₯
NULL
π¦ PROTOCOLS π¦
This functionality affects all supported protocols. All of them. Every single one. Universal slay β¨
π EXAMPLE π
int main(void)
{
CURL *curl;
struct curl_slist *host = NULL;
host = curl_slist_append(NULL, "example.com:443:127.0.0.1");
host = curl_slist_append(host, "example.com:443:[2001:db8::252f:efd6]");
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_slist_free_all(host);
}
Two addresses for the same example.com:443 pair, one IPv4 and one bracketed IPv6 β chef's kiss π Note the /* always cleanup */ comment, because we always clean up in this house π«Ά
β HISTORY β
A little timeline for the history girlies π:
- Added in
7.21.3. Removal support added in7.42.0. - Support for providing the
ADDRESSwithin[brackets]was added in7.57.0. - Support for providing multiple IP addresses per entry was added in
7.59.0. - Support for adding non-permanent entries by using the
+prefix was added in7.75.0. - Support for specifying the host component as an IPv6 address was added in
8.13.0.
Glow-up after glow-up, we love to see it π
π AVAILABILITY π
Added in curl 7.21.3. Available to you, bestie, since forever-ish. π
π RETURN VALUE π
curl_easy_setopt(3) returns a CURLcode indicating success or error.
CURLE_OK (0) means everything was OK β slay π β and non-zero means an error occurred, so go check libcurl-errors(3). Don't ignore the error code, it's telling you something, iykyk.
π§ SEE ALSO π§
Heads up bestie: that list is not copied by libcurl, so keep it alive until the transfer finishes. And remember -HOST:PORT removal needs an exact host+port match. No shortcut, no guessing π
That's the whole page, bestie! This one comes to you from the libcurl manual, source/version libcurl, dated 2026-10-12 β go forth and fake your DNS with confidence πΈπβ¨
π¦ where this page comes from
- fedora 44: libcurl-devel 8.18.0-14.fc44 Β· curl
- fedora 44: libcurl-devel 8.18.0-14.fc44 Β· curl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms