Enable HTTP/3 in PHP Curl: Build, Detect, and Send Requests
This guide explains how to compile the PHP Curl extension with experimental HTTP/3 support, detect whether Curl supports HTTP/3, and use PHP code to issue HTTP/3 requests, including required libraries, build steps, and practical code examples.
Overview of HTTP/3 and Curl Support
HTTP/3 is the third major version of the HTTP protocol and runs on top of the QUIC multiplexed UDP transport. It retains the same request‑header, method, response and status‑code semantics as HTTP/1.1 and HTTP/2 while offering lower latency and higher throughput. All major browsers support HTTP/3, and client tools such as curl, Nginx and LiteSpeed provide experimental support. Caddy Server enables HTTP/3 by default.
Sending HTTP/3 Requests with the PHP Curl Extension
Prerequisites
Curl must be built with HTTP/3 support (requires libcurl compiled with QUIC libraries).
Curl version 7.66 or newer.
PHP 8.2 or newer.
Basic Usage
Set the CURLOPT_HTTP_VERSION option to the constant CURL_HTTP_VERSION_3. If the constant is missing (PHP 8.3 and earlier), define it manually or pass the numeric value 30.
$ch = curl_init("https://php.watch/");
if (!defined('CURL_HTTP_VERSION_3')) {
define('CURL_HTTP_VERSION_3', 30);
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3);
curl_exec($ch);When Curl is built with HTTP/3, the request succeeds and the response header block begins with HTTP/3 200. If the remote server does not support HTTP/3, Curl silently falls back to the highest version it can negotiate.
Strict HTTP/3 Only
Use the constant CURL_HTTP_VERSION_3ONLY (value 31) to require HTTP/3. Curl will fail if either side lacks HTTP/3 support.
if (!defined('CURL_HTTP_VERSION_3ONLY')) {
define('CURL_HTTP_VERSION_3ONLY', 31);
}
$ch = curl_init("https://php.watch/");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3ONLY);
curl_exec($ch);Detecting HTTP/3 Support in the PHP Curl Extension
phpinfo() / php -i
Running phpinfo() or php -i shows a "curl" section. If the "HTTP/3" line appears, the underlying libcurl was compiled with QUIC support.
curl_version() Bitmask
The curl_version() function returns an associative array. The features element is a bitmask; the flag CURL_VERSION_HTTP3 (if defined) indicates HTTP/3 support.
if (defined('CURL_VERSION_HTTP3') && (curl_version()['features'] & CURL_VERSION_HTTP3)) {
// HTTP/3 is available
}curl_setopt Return Value
When CURLOPT_HTTP_VERSION is set to CURL_HTTP_VERSION_3, curl_setopt returns false if the installed libcurl lacks HTTP/3. In that case reset the option to null so Curl can negotiate the best available version.
$ch = curl_init("https://php.watch/");
$ok = curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3);
if ($ok === false) {
curl_setopt($ch, CURLOPT_HTTP_VERSION, null);
}
curl_exec($ch);Building libcurl with HTTP/3 Support
Required Libraries
WolfSSL(built with --enable-quic and related options). nghttp3 (HTTP/3 framing library). ngtcp2 (QUIC transport library).
Build Steps
All commands assume a home directory workspace ( ~/curl and ~/build). Adjust --prefix paths if you place the builds elsewhere.
# Prepare workspace
cd ~
mkdir -p curl build && cd curl
# Build WolfSSL
git clone https://github.com/wolfSSL/wolfssl.git
cd wolfssl
autoreconf -fi
./configure --prefix=~/build/wolfssl \
--enable-quic --enable-session-ticket \
--enable-earlydata --enable-psk \
--enable-harden --enable-altcertchains
make && make install
cd ..
# Build nghttp3 (v1.0.0)
git clone -b v1.0.0 https://github.com/ngtcp2/nghttp3
cd nghttp3
autoreconf -fi
./configure --prefix=~/build/nghttp3 --enable-lib-only
make && make install
cd ..
# Build ngtcp2 (v1.0.1)
git clone -b v1.0.1 https://github.com/ngtcp2/ngtcp2
cd ngtcp2
autoreconf -fi
PKG_CONFIG_PATH=~/build/wolfssl/lib/pkgconfig:~/build/nghttp3/lib/pkgconfig \
LDFLAGS="-Wl,-rpath,~/build/wolfssl/lib" \
./configure --prefix=~/build/ngtcp2 --enable-lib-only --with-wolfssl
make && make install
cd ..
# Build libcurl with the QUIC stack
git clone https://github.com/curl/curl.git
cd curl
autoreconf -fi
./configure --with-wolfssl=~/build/wolfssl \
--with-nghttp3=~/build/nghttp3 \
--with-ngtcp2=~/build/ngtcp2
make && make installCompiling the PHP Curl Extension Against the New libcurl
After installing the custom libcurl system‑wide (or in a non‑standard prefix), rebuild PHP with the --with-curl configure flag pointing to the libcurl location.
sudo apt install build-essential autoconf libtool bison re2c
git clone https://github.com/php/php-src.git --branch=master
cd php-src
./buildconf
./configure --with-curl # add --with-curl=/custom/path if needed
make -j $(nproc)
sudo make installExample: Issuing an HTTP/3 Request
On a system where the rebuilt PHP uses an HTTP/3‑enabled libcurl, the following script forces an HTTP/3 request.
$ch = curl_init("https://www.tinywan.com/");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3);
curl_exec($ch);Caveats and Maintenance Considerations
The PHP Curl extension built this way is experimental; future libcurl or PHP releases may change the required build flags.
Pre‑built distribution packages (Debian/Ubuntu, Fedora/RHEL) do not include HTTP/3 support, so manual compilation is required.
Using OpenSSL variants other than WolfSSL has been observed to cause segmentation faults when combined with QUIC libraries.
Because the extension is compiled from source, you must manually apply security patches and rebuild when new libcurl or PHP versions are released.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
