CURLOPT_ECH(3)
π CURLOPT_ECH(3) π
okay so bestie, welcome to the libcurl manual, this one's all about CURLOPT_ECH β the config knob for Encrypted Client Hello πβ¨
πΈ NAME πΈ
CURLOPT_ECH β configuration for Encrypted Client Hello π¦
β¨ SYNOPSIS β¨
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ECH, char *config);
π DESCRIPTION π
okay first thing: ECH is only compatible with TLSv1.3. no cap, that's the rule π₯
This is an experimental feature, and it needs a special build of OpenSSL, because ECH is not yet supported in OpenSSL releases. meanwhile the latest BoringSSL, wolfSSL and Rustls-ffi releases do support ECH, so likeβ¦ pick your fighter π
There's also a known issue with using wolfSSL β it does not support ECH when the HelloRetryRequest mechanism is used. π just so you know.
So you pass a string that specifies configuration details for ECH. In all cases, if ECH is attempted, it may fail for various reasons. π The keywords supported are:
falseβ turns off ECH. bye bye πgreaseβ instructs client to emit a GREASE ECH extension. (heads up: the connection fails if ECH is attempted but fails.) πtrueβ instructs client to attempt ECH, if possible, but to not fail if attempting ECH is not possible. soft launch energy β¨hardβ instructs client to attempt ECH and fail if attempting ECH is not possible. main character commitment, no backup plan π₯ecl:<base64-value>β if the string starts withecl:then the remainder of the string should be a base64-encodedECHConfigListthat is used for ECH rather than attempting to download such a value from the DNS. straight to the source, we love to see it πpn:<name>β if the string starts withpn:then the remainder of the string should be a DNS/hostname that is used to over-ride thepublic_namefield of theECHConfigListthat is used for ECH. glow-up for the public name π
bestie, the good news: the application does not have to keep the string around after setting this option. set it and forget it π«Ά
Using this option multiple times makes the last set string override the previous ones. and set it to NULL or "false" to disable its use again. so simple, iconic π
π¦ DEFAULT π¦
NULL, meaning ECH is disabled. she's off, she's resting π§
π PROTOCOLS π
This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc. β
This option works only with the following TLS backends: OpenSSL, Rustls and wolfSSL π
π EXAMPLE π
int main(void)
{
CURL *curl = curl_easy_init();
const char *config = \
"ecl:AED+DQA87wAgACB/RuzUCsW3uBbSFI7mzD63TUXpI8sGDTnFTbFCDpa+" \
"CAAEAAEAAQANY292ZXIuZGVmby5pZQAA";
if(curl) {
curl_easy_setopt(curl, CURLOPT_ECH, config);
curl_easy_perform(curl);
}
}
π AVAILABILITY π
Added in curl 8.8.0 π (yes we're so back)
π RETURN VALUE π
curl_easy_setopt(3) returns a CURLcode indicating success or error.
CURLE_OK (0) means everything was OK πβ¨, non-zero means an error occurred π, see libcurl-errors(3).
π SEE ALSO π
k that's the whole thing bestie, go encrypt those hellos πβ¨π
this lil page came from libcurl, dated 2026-10-12 β periodt, iykyk π¦π
π¦ 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