libcurl promises API stability and guarantees that your program written today will remain working in the future. We do not break compatibility.
Over time, we add features, new options and new functions to the APIs but we do not change behavior in a non-compatible way or remove functions.
The last time we changed the API in an non-compatible way was for 7.16.0 in 2006 and we plan to never do it again.
Curl and libcurl are individually versioned, but they mostly follow each other rather closely.
The version numbering is always built up using the same system:
X.Y.Z
- X is main version number
- Y is release number
- Z is patch number
One of these X.Y.Z numbers will get bumped in every new release. The numbers to the right of a bumped number will be reset to zero.
The main version number X is bumped when really big, world colliding changes are made. The release number Y is bumped when changes are performed or things/features are added. The patch number Z is bumped when the changes are mere bugfixes.
It means that after a release 1.2.3, we can release 2.0.0 if something really big has been made, 1.3.0 if not that big changes were made or 1.2.4 if mostly bugs were fixed.
Bumping, as in increasing the number with 1, is unconditionally only affecting one of the numbers (and the ones to the right of it are set to zero). 1 becomes 2, 3 becomes 4, 9 becomes 10, 88 becomes 89 and 99 becomes 100. So, after 1.2.9 comes 1.2.10. After 3.99.3, 3.100.0 might come.
All original curl source release archives are named according to the libcurl version (not according to the curl client version that, as said before, might differ).
As a service to any application that might want to support new libcurl
features while still being able to build with older versions, all releases
have the libcurl version stored in the curl/curlver.h
file using a static
numbering scheme that can be used for comparison. The version number is
defined as:
#define LIBCURL_VERSION_NUM 0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in hexadecimal. All three number fields are always represented using two digits (eight bits each). 1.2.0 would appear as "0x010200" while version 9.11.7 appears as "0x090b07".
This 6-digit hexadecimal number is always a greater number in a more recent release. It makes comparisons with greater than and less than work.
This number is also available as three separate defines:
LIBCURL_VERSION_MAJOR
, LIBCURL_VERSION_MINOR
and LIBCURL_VERSION_PATCH
.
These defines are, of course, only suitable to figure out the version number built just now and they will not help you figuring out which libcurl version that is used at run-time three years from now.
To figure out which libcurl version that your application is using right
now, curl_version_info()
is there for you.
Applications should use this function to judge if things are possible to do or not, instead of using compile-time checks, as dynamic/DLL libraries can be changed independent of applications.
curl_version_info() returns a pointer to a struct with information about
version numbers and various features and in the running version of
libcurl. You call it by giving it a special age counter so that libcurl knows
the "age" of the libcurl that calls it. The age is a define called
CURLVERSION_NOW
and is a counter that is increased at irregular intervals
throughout the curl development. The age number tells libcurl what struct set
it can return.
You call the function like this:
curl_version_info_data *ver = curl_version_info( CURLVERSION_NOW );
The data will then be pointing at struct that has or at least can have the following layout:
struct {
CURLversion age; /* see description below */
/* when 'age' is 0 or higher, the members below also exist: */
const char *version; /* human readable string */
unsigned int version_num; /* numeric representation */
const char *host; /* human readable string */
int features; /* bitmask, see below */
char *ssl_version; /* human readable string */
long ssl_version_num; /* not used, always zero */
const char *libz_version; /* human readable string */
const char * const *protocols; /* protocols */
/* when 'age' is 1 or higher, the members below also exist: */
const char *ares; /* human readable string */
int ares_num; /* number */
/* when 'age' is 2 or higher, the member below also exists: */
const char *libidn; /* human readable string */
/* when 'age' is 3 or higher (7.16.1 or later), the members below also
exist */
int iconv_ver_num; /* '_libiconv_version' if iconv support enabled */
const char *libssh_version; /* human readable string */
/* when 'age' is 4 or higher, the member below also exists: */
unsigned int brotli_ver_num; /* Numeric Brotli version
(MAJOR << 24) | (MINOR << 12) | PATCH */
const char *brotli_version; /* human readable string. */
/* when 'age' is 5 or higher, the member below also exists: */
unsigned int nghttp2_ver_num; /* Numeric nghttp2 version
(MAJOR << 16) | (MINOR << 8) | PATCH */
const char *nghttp2_version; /* human readable string. */
const char *quic_version; /* human readable quic (+ HTTP/3) library +
version or NULL */
/* when 'age' is 6 or higher, the member below also exists: */
const char *cainfo; /* the built-in default CURLOPT_CAINFO, might
be NULL */
const char *capath; /* the built-in default CURLOPT_CAPATH, might
be NULL */
/* when 'age' is 7 or higher, the member below also exists: */
unsigned int zstd_ver_num; /* Numeric Zstd version
(MAJOR << 24) | (MINOR << 12) | PATCH */
const char *zstd_version; /* human readable string. */
/* when 'age' is 8 or higher, the member below also exists: */
const char *hyper_version; /* human readable string. */
} curl_version_info_data;