cpp-httplib: a single-header HTTP/HTTPS server and client for C++
A C++ header-only HTTP/HTTPS server and client library. [!NOTE] BoringSSL (best-effort): BoringSSL builds under CPPHTTPLIB_OPENSSL_SUPPORT and is exercised by CI against current upstream.
At a glance
- What is it?
- cpp-httplib puts a blocking HTTP/1.1 server and client in one header file. It is a good fit for small services, tests and internal tools, and the wrong fit for anything that needs HTTP/2, HTTP/3 or 32-bit targets.
- Who is it for?
- Adopt cpp-httplib when you want an HTTP server or client inside a C++ program without adding a build dependency, and when HTTP/1.1 over blocking sockets is enough. Do not adopt it for HTTP/2 or HTTP/3 workloads, for 32-bit targets, or when you need non-blocking I/O.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem cpp-httplib solves, and for whom
Most C++ projects that need to speak HTTP face the same choice: link a C library such as libcurl and write glue code, or pull in a framework with its own build system, its own abstractions and its own release cadence. cpp-httplib takes a third route. It is a single header, httplib.h, that you copy into your tree and include. The README states the setup in one line: "Just include the httplib.h file in your code!" There is no library to link for plain HTTP, no package manager step, and no generated code.
The audience is narrow and specific. It suits someone writing a small service, a test double, a local tool, or an embedded HTTP endpoint inside a larger C++ program, where the HTTP layer is a means rather than the product. It also suits client-side code that needs to call a REST endpoint from inside an existing C++ application without adding a dependency that has to be installed on every build machine.
It is not aimed at people who need HTTP/2 or HTTP/3. The README is explicit: "Only HTTP/1.1 is supported. HTTP/2 and HTTP/3 are not implemented." It is also not aimed at anyone who needs non-blocking socket I/O. The project states that it uses blocking sockets and that if you want non-blocking I/O, "this is not the one that you want." Those two sentences remove a large class of potential users, and the project says so up front rather than burying it.
What the blocking, header-only design actually implies
The mechanism is straightforward. A server is an instance of httplib::Server, and routes are registered as lambdas keyed by method and path. The README example registers svr.Get("/hi", ...) and then calls svr.listen("0.0.0.0", 8080). The client is an httplib::Client constructed from a URL, and a request returns an optional-like result you test before reading status or body.
Because the I/O is blocking, each connection occupies a thread for the duration of its handling unless you supply a thread pool. The repository contains test/test_thread_pool.cc and a justfile target `just others` that builds and runs it, which suggests the project treats threading as something you configure rather than something the library hides. That is a real architectural decision with a real cost: concurrency is your problem, and a slow handler ties up a thread.
SSL/TLS is layered on through a compile-time define. The README lists three backends in a table: OpenSSL under CPPHTTPLIB_OPENSSL_SUPPORT (3.0 or later required), Mbed TLS under CPPHTTPLIB_MBEDTLS_SUPPORT (2.x, 3.x and 4.x, auto-detected), and wolfSSL under CPPHTTPLIB_WOLFSSL_SUPPORT (5.x, built with --enable-opensslall). BoringSSL is listed separately as best-effort: it builds under CPPHTTPLIB_OPENSSL_SUPPORT and is exercised by CI, but the README warns that BoringSSL does not guarantee API stability, that its public headers require C++14 or later, and that hostname verification is SAN-only with no CN fallback.
The split.py and generate_module.py files at the top level, plus meson.build and CMakeLists.txt, indicate the single header is generated from a split source tree rather than hand-maintained. That matters if you plan to patch it: your change has to survive regeneration, and the upstream source is what you should be reading.
Installing cpp-httplib and serving a first route
The README gives no package-manager instructions and does not describe a vcpkg or CMake install flow, so the documented path is to take the header directly. The README links the raw file at raw.githubusercontent.com/yhirose/cpp-httplib/refs/heads/master/httplib.h. Download it into your include directory and compile with C++11 or later.
A minimal server needs the header, a Server object, one route, and a listen call. The README shows this shape:
#include "path/to/httplib.h"
int main() {
httplib::Server svr;
svr.Get("/hi", [](const httplib::Request &, httplib::Response &res) {
res.set_content("Hello World!", "text/plain");
});
svr.listen("0.0.0.0", 8080);
}Compile it with a C++11-or-later flag and run it. A request to http://localhost:8080/hi should return the body Hello World! with the content type text/plain. There is a ready-made example in the repository at example/hello.cc if you prefer to start from something already wired up.
The client side follows the same pattern. The README constructs a client from a full URL and checks the result before touching it:
httplib::Client cli("http://yhirose.github.io");
if (auto res = cli.Get("/hi")) {
res->status;
res->body;
}If you want HTTPS, add the define before the include and use an https:// URL. The README shows both forms, and for a client with a custom CA bundle it shows cli.set_ca_cert_path("./ca-bundle.crt"). Note that disabling verification requires two separate calls in the README: enable_server_certificate_verification(false) for the certificate and a second call for host verification. Treat both as debugging aids, not as a deployment configuration.
For a container-based trial, the repository ships a Dockerfile and docker-compose.yml. The compose file maps port 8080 on the host to port 80 in the container and mounts ./docker/html at /html. The Dockerfile builds a static binary with g++ -std=c++23 and runs it from a scratch image with the entrypoint arguments --host 0.0.0.0 --port 80 --mount /:./html. That is the fastest way to see the server running without setting up a local toolchain, and it also shows the flag names the project's own demo binary accepts.
Where cpp-httplib is the wrong tool
The 32-bit warning is the sharpest limitation in the README, and it is unusually blunt. The project states that 32-bit platforms are not supported, that the library may compile on them but no security review has been conducted, that integer truncation and other 32-bit-specific issues may exist, and that security reports affecting only 32-bit platforms will be closed without action. CI, the README says, includes basic compile checks only, not functional or security testing. If you ship to a 32-bit embedded target, this is a disqualifying statement, not a caveat.
The TLS abstraction has a documented gap. The README notes that under Mbed TLS and wolfSSL, get_ca_certs() and get_ca_names() only reflect certificates loaded through load_ca_cert_store(). Certificates loaded through set_ca_cert_path() or through system certificates are not enumerable. If your code inspects the trust store at runtime, that behaviour differs from what you might assume, and it differs between backends.
Blocking I/O is the third boundary. A server that handles long-lived connections, streaming uploads from many clients, or anything resembling a high-concurrency gateway will spend most of its time waiting on threads. The library gives you HTTP, not a concurrency model. For a service whose main job is to hold thousands of idle connections open, a non-blocking framework is the correct choice, and the project says as much in its own note.
Finally, the header is generated. Anyone who forks and edits httplib.h directly, without touching the split sources, will find the next upstream regeneration overwrites the work. The presence of split.py and generate_module.py is the tell.
cpp-httplib compared with libcurl and Boost.Beast
The most common comparison is with libcurl, and the difference is in what each one is. libcurl is a client library with a C API and a large set of protocol backends; it does not give you a server. cpp-httplib gives you both a server and a client in one header, but only over HTTP/1.1. If your program only needs to make outbound requests, libcurl covers more protocols and has a longer track record. If your program needs to accept inbound requests too, cpp-httplib removes an entire build dependency.
The comparison with Boost.Beast is about dependencies and control. Beast is built on Boost.Asio and gives you access to asynchronous I/O and a lower-level HTTP message model. cpp-httplib hands you a route table and blocking calls. Beast asks you to understand Asio's executor and buffer model; cpp-httplib asks you to understand almost nothing. The trade is that Beast lets you scale a connection-handling design in ways cpp-httplib does not attempt, while cpp-httplib keeps the build simple. If you are already a Boost shop, the marginal cost of Beast is lower than it looks; if you are not, adding Boost to get an HTTP endpoint is a heavy step.
Against Crow, the difference is again packaging and scope. Crow is a web framework with routing and templating built around a specific application shape. cpp-httplib is closer to a protocol library: routes exist, but there is no view layer and no application scaffolding. Which one is right depends on whether you want a framework or a transport.
Maintenance, licensing and the cost of upgrading
The repository is not archived, and the last push was on 2026-08-28. The most recent release listed is v0.54.0 on the same date, with v0.53.1 on 2026-08-15 and v0.53.0 on 2026-08-09. Releases are frequent and versioned, so the practical upgrade cost is mostly about reading the changelog between the version you vendored and the one you are moving to.
Because the library is a header you copy, upgrading is a file replacement rather than a package-manager operation, unless you consume it through a package manager you set up yourself. That cuts both ways. There is no lockfile to update and no transitive dependency graph to resolve, but there is also nothing that tells you a new version exists. If you vendor httplib.h, you own the decision to move, and you own the diff.
The MIT licence is permissive and short. It permits use, modification and redistribution with the licence text retained. That is the whole of the licence implication here; anything beyond that depends on your own legal review, and the repository's LICENSE file is the authority rather than this summary.
One maintenance detail worth noting: the project's own justfile shows separate test targets per TLS backend (openssl, mbedtls, wolfssl, no_tls) plus parallel variants. That structure implies backend-specific breakage is possible, so if you build with Mbed TLS or wolfSSL, test your own configuration rather than assuming the OpenSSL path covers you.
Editorial conclusion
Adopt cpp-httplib when you want an HTTP server or client inside a C++ program without adding a build dependency, and when HTTP/1.1 over blocking sockets is enough. Do not adopt it for HTTP/2 or HTTP/3 workloads, for 32-bit targets, or when you need non-blocking I/O. Before committing, check that your TLS backend matches one of the three the README lists, that your compiler is C++11 or later (C++14 or later if you build against BoringSSL), and that you can live with the fact that get_ca_certs() only enumerates certificates loaded through load_ca_cert_store().
Frequently asked questions
What is cpp-httplib?
It is a C++11 single-file header-only cross-platform HTTP/HTTPS library, according to the README. It provides both a server and a client, and you use it by including httplib.h in your code.
How do I install cpp-httplib?
The README does not describe a package-manager install. It links the raw httplib.h file and says to include it in your code, so the documented path is to download the header into your project and compile with C++11 or later.
How do I use cpp httplib?
Create an httplib::Server, register a route with svr.Get("/hi", ...), and call svr.listen("0.0.0.0", 8080). For client requests, construct an httplib::Client from a URL and call cli.Get("/hi"), checking the returned result before reading status or body.
How do I write an HTTP client in C++ with cpp-httplib?
Construct httplib::Client with a URL such as http://yhirose.github.io, call Get on a path, and test the returned value before accessing res->status or res->body. For HTTPS, define CPPHTTPLIB_OPENSSL_SUPPORT before including the header and use an https:// URL.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/yhirose-cpp-httplib)