Open-Source Wikis

/

curl

/

Libraries

/

libcurl

curl/curl

libcurl

Active contributors: Daniel Stenberg, Viktor Szakats, Stefan Eissing, Jay Satiro

Purpose

libcurl is curl's portable C library for transferring data with URLs. It is reentrant, thread-safe (when used with care — one easy handle per thread), supports concurrent transfers via the multi interface, and has a stable API and ABI: SONAME 4 since 2006, no public-API removals, ~308 curl_easy_setopt() options as of late 2025.

Public surface

All public symbols live in include/curl/:

Header Contents
include/curl/curl.h Easy interface, options enum, CURLcode, callbacks
include/curl/easy.h Easy-interface convenience functions
include/curl/multi.h Multi interface, curl_multi_*, curl_socket_*
include/curl/urlapi.h URL parser/builder API
include/curl/header.h HTTP-header inspection API
include/curl/websockets.h WebSocket framing API
include/curl/options.h Programmatic option metadata (typeof, name, ID)
include/curl/system.h curl_off_t and platform-specific integer typedefs
include/curl/typecheck-gcc.h Compile-time typecheck shims for curl_easy_setopt
include/curl/mprintf.h Project's printf, exported for embedders
include/curl/curlver.h Version macros (LIBCURL_VERSION_*)
include/curl/stdcheaders.h Header-include compatibility shim

The library exports its entire public API via lib/libcurl.def and lib/libcurl.vers.in.

Directory layout

The implementation under lib/ has ~184 .c and ~178 .h files, divided by purpose. The largest are:

File Purpose
lib/url.c (113 KB) Setup, teardown, scheme dispatch, connection-cache lookups
lib/multi.c (128 KB) The multi state machine — the heart of the library
lib/easy.c The blocking wrappers around the multi interface
lib/transfer.c The per-transfer outer loop (SINGLEREQUEST etc.)
lib/setopt.c (84 KB) Dispatch for every curl_easy_setopt value
lib/getinfo.c Dispatch for curl_easy_getinfo
lib/easyoptions.c Auto-generated option metadata table
lib/cfilters.c Connection filter framework
lib/conncache.c Connection cache + pooling
lib/connect.c TCP connection establishment
lib/cf-socket.c (69 KB) Socket-level connection filter
lib/dnscache.c Resolved-address cache
lib/hostip.c DNS resolution glue (sync + async dispatch)
lib/asyn-ares.c c-ares async resolver backend
lib/asyn-thrdd.c Thread-pool async resolver backend
lib/doh.c DNS-over-HTTPS resolver
lib/sendf.c (40 KB) Send/recv plumbing, "client write" pipeline
lib/cw-out.c, lib/cw-pause.c Client-write filters (decompress, pause)
lib/content_encoding.c gzip / deflate / brotli / zstd
lib/headers.c HTTP-header inspection API implementation
lib/cookie.c Cookie engine
lib/hsts.c HSTS cache
lib/altsvc.c Alt-Svc cache
lib/urlapi.c (56 KB) URL parser/builder (curl_url_*)
lib/mime.c (62 KB) Multipart/MIME builder
lib/formdata.c Legacy curl_formadd (deprecated, kept for ABI)
lib/version.c curl_version_info() and version string assembly
lib/share.c / lib/curl_share.c Share-handle implementation
lib/curl_setup.h (48 KB) Compile-time configuration: every CURL_DISABLE_* and USE_* lives here
lib/urldata.h (58 KB) The internal data model: Curl_easy, connectdata, SessionHandle

Subdirectories implement abstracted backends:

Directory Concept Backends
lib/vtls/ TLS OpenSSL, GnuTLS, mbedTLS, Schannel, wolfSSL, Rustls, Apple SecTrust
lib/vquic/ QUIC + HTTP/3 ngtcp2 (with multiple TLS), quiche
lib/vauth/ Authentication mechanisms NTLM, Digest, SASL, Kerberos GSAPI, SPNEGO, OAuth2
lib/vssh/ SSH (SCP/SFTP) libssh2, libssh, wolfSSH
lib/curlx/ Internal portability n/a

How it works

The transfer engine is a non-blocking state machine (Transfer engine). Every public entry point — curl_easy_perform, curl_multi_perform, curl_multi_socket_action — eventually drives Curl_multi_runsingle() in lib/multi.c. Each easy handle progresses through a sequence of states, each implemented by a small handler. Between states, the library yields back to the application.

Connections are abstracted as a stack of connection filters. The protocol handler at the top sees a virtual byte stream; underneath, filters provide HTTP/2 multiplexing, TLS encryption, SOCKS or HTTP CONNECT proxying, and finally a socket. Adding a new transport (e.g. a new TLS backend or proxy variant) is a matter of writing a new filter and inserting it into the chain.

graph TD
    Public[Public API: curl_easy/multi/url] --> Setopt[setopt.c]
    Public --> EasyMulti[easy.c, multi.c]
    EasyMulti --> Transfer[transfer.c]
    Transfer --> Handlers[Curl_protocol handlers<br/>http.c, ftp.c, smtp.c, …]
    Handlers --> CFilters[Curl_cfilter chain]
    CFilters --> Filters[cf-socket, vtls, http2, vquic, h1-proxy, h2-proxy, socks, …]
    EasyMulti --> Caches[conncache, dnscache, vtls_scache, hsts, altsvc]
    EasyMulti --> Resolver[hostip + asyn-* + doh]

Threading model

libcurl itself does not start threads except for the asyn-thrdd resolver pool (lib/thrdpool.c, lib/thrdqueue.c) and any threading inside third-party backends (e.g. OpenSSL's locking). Concurrency at the application level is done by giving each thread its own easy handle, or by sharing a multi handle with appropriate locking.

The share interface (lib/curl_share.c) lets multiple easy handles share caches (DNS, connection, cookies, TLS sessions, HSTS, PSL); the application supplies lock callbacks via CURLSHOPT_LOCKFUNC/CURLSHOPT_UNLOCKFUNC.

Building

The two build systems live in Makefile.am/configure.ac and CMakeLists.txt. The set of compiled features is controlled by CURL_DISABLE_* and USE_* macros that are exposed by both. See Architecture and lib/curl_setup.h for the toggle list.

Symbol visibility and ABI

  • CURL_EXTERN (defined in include/curl/curl.h) marks every public symbol. The build hides everything else on platforms that support it (-fvisibility=hidden, __declspec(dllimport/dllexport), version scripts).
  • The Linux SONAME is libcurl.so.4 and has been since 2006. ABI breakages are not tolerated; new fields go onto opaque structs accessed via curl_*_setopt/curl_*_getinfo.
  • The version-script template lib/libcurl.vers.in keeps unstable internals out of the export set.

Entry points for modification

  • A new public option → add a CURLOPT_* enum value in include/curl/curl.h, register it in lib/easyoptions.c, dispatch in lib/setopt.c, store in struct Curl_easy::set (lib/urldata.h), document in docs/libcurl/opts/CURLOPT_*.md. See Patterns.
  • A new TLS backend → see lib/vtls/openssl.c as a reference and copy the Curl_ssl vtable shape; register the backend in lib/vtls/vtls.c.
  • A new protocol handler → declare a const struct Curl_protocol (lib/protocol.h), implement its do_it/done/connecting/etc. callbacks, and register it in lib/url.c.
  • Changes to the multi state machine → lib/multi.c::Curl_multi_runsingle and the state_* helpers below it.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

libcurl – curl wiki | Factory