[packages/curl-impersonate] Initial
arekm
arekm at pld-linux.org
Sat Jun 6 15:38:23 CEST 2026
commit c290869f62de8c836dda49345e78b276a57231a6
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Sat Jun 6 15:37:49 2026 +0200
Initial
curl-impersonate-build.patch | 117 ++++++++++++++++++++++++++++++
curl-impersonate.spec | 165 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 282 insertions(+)
---
diff --git a/curl-impersonate.spec b/curl-impersonate.spec
new file mode 100644
index 0000000..91eba1f
--- /dev/null
+++ b/curl-impersonate.spec
@@ -0,0 +1,165 @@
+#
+# curl-impersonate is patched curl + BoringSSL + an HTTP/2,3 stack that mimics
+# real browser TLS/HTTP fingerprints. Only the fingerprint-critical pieces are
+# bundled and statically linked: BoringSSL (pinned commit, patched), ngtcp2 and
+# nghttp3 (patched), and nghttp2 pinned to 1.63 (>=1.65 drops the priority flag
+# the HTTP/2 fingerprint relies on) - none have a usable PLD counterpart. The
+# unpatched, fingerprint-irrelevant zlib/zstd/brotli/libidn2 come from PLD.
+#
+%define boring_commit 673e61fc215b178a90c0e67858bbf162c8158993
+%define curl_tag curl-8_15_0
+%define nghttp2_version 1.63.0
+%define ngtcp2_version 1.20.0
+%define nghttp3_version 1.15.0
+Summary: curl that impersonates real browser TLS/HTTP fingerprints
+Summary(pl.UTF-8): curl podszywający się pod odciski TLS/HTTP prawdziwych przeglądarek
+Name: curl-impersonate
+Version: 1.5.6
+Release: 1
+License: MIT (curl-impersonate, curl, nghttp2/3, ngtcp2), BoringSSL
+Group: Applications/Networking
+URL: https://github.com/lexiforest/curl-impersonate
+Source0: https://github.com/lexiforest/curl-impersonate/archive/v%{version}/%{name}-%{version}.tar.gz
+# Source0-md5: c220749405028695f55e224271374f3e
+Source1: https://github.com/curl/curl/archive/%{curl_tag}.tar.gz
+# Source1-md5: 246e64770431f2a19c3f5c26bc83cb95
+Source2: https://github.com/google/boringssl/archive/%{boring_commit}/boringssl-%{boring_commit}.zip
+# Source2-md5: 843d1d9e4b80477d21771f2a872b9edc
+Source3: https://github.com/nghttp2/nghttp2/releases/download/v%{nghttp2_version}/nghttp2-%{nghttp2_version}.tar.bz2
+# Source3-md5: c29228929c3c323ecd0eae172f1eb9d5
+Source4: https://github.com/ngtcp2/ngtcp2/releases/download/v%{ngtcp2_version}/ngtcp2-%{ngtcp2_version}.tar.bz2
+# Source4-md5: 15881f426f0236956f52b3def11eb9a9
+Source5: https://github.com/ngtcp2/nghttp3/releases/download/v%{nghttp3_version}/nghttp3-%{nghttp3_version}.tar.bz2
+# Source5-md5: b1fd62a123652b878efb23fb34a8d5e0
+Patch0: %{name}-build.patch
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: cmake >= 3.5
+BuildRequires: libbrotli-devel
+BuildRequires: libidn2-devel
+BuildRequires: libstdc++-devel
+BuildRequires: libtool
+BuildRequires: ninja
+BuildRequires: pkgconfig
+BuildRequires: unzip
+BuildRequires: zlib-devel
+BuildRequires: zstd-devel
+BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
+
+%description
+curl-impersonate is a special build of curl that can impersonate the
+four major browsers: Chrome, Edge, Safari and Firefox. It performs TLS
+and HTTP handshakes identical to a real browser, so it is much harder
+to fingerprint and block. It ships a libcurl-impersonate shared
+library and the curl-impersonate command line tool with per-browser
+wrapper scripts.
+
+%description -l pl.UTF-8
+curl-impersonate to specjalna wersja curla, która potrafi podszywać
+się pod cztery główne przeglądarki: Chrome, Edge, Safari i Firefox.
+Wykonuje uzgodnienia TLS i HTTP identyczne jak prawdziwa przeglądarka,
+dzięki czemu znacznie trudniej ją rozpoznać i zablokować. Zawiera
+bibliotekę współdzieloną libcurl-impersonate oraz narzędzie wiersza
+poleceń curl-impersonate ze skryptami opakowującymi dla poszczególnych
+przeglądarek.
+
+%package libs
+Summary: libcurl-impersonate shared library
+Summary(pl.UTF-8): Biblioteka współdzielona libcurl-impersonate
+Group: Libraries
+
+%description libs
+libcurl-impersonate shared library - a drop-in libcurl replacement
+that performs browser-identical TLS and HTTP fingerprints.
+
+%description libs -l pl.UTF-8
+Biblioteka współdzielona libcurl-impersonate - zamiennik libcurl
+wykonujący uzgodnienia TLS i HTTP identyczne jak przeglądarki.
+
+%package devel
+Summary: Header files for libcurl-impersonate library
+Summary(pl.UTF-8): Pliki nagłówkowe biblioteki libcurl-impersonate
+Group: Development/Libraries
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+
+%description devel
+Header files for the libcurl-impersonate library. The headers are
+installed into a private %{_includedir}/curl-impersonate directory so
+they do not conflict with the standard curl-devel package.
+
+%description devel -l pl.UTF-8
+Pliki nagłówkowe biblioteki libcurl-impersonate. Nagłówki instalowane
+są w prywatnym katalogu %{_includedir}/curl-impersonate, aby nie
+kolidowały ze standardowym pakietem curl-devel.
+
+%prep
+%setup -q
+%patch -P0 -p1
+
+# Place the pinned dependency archives where upstream's Makefile expects them,
+# so the network-isolated build uses them instead of downloading.
+cp -p %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} .
+
+%build
+%configure
+export CFLAGS="%{rpmcflags} %{rpmcppflags} -fPIC"
+export CXXFLAGS="%{rpmcxxflags} %{rpmcppflags} -fPIC"
+export LDFLAGS="%{rpmldflags}"
+# The top-level make must stay serial: several dependency rules list two
+# targets sharing one recipe (e.g. libbrotli{common,dec}.a), which race under
+# -j. Parallelism is delegated to each sub-build via SUBJOBS.
+%{__make} -j1 build \
+ SUBJOBS=%{__jobs}
+%{__make} -j1 checkbuild
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+%{__make} -C %{curl_tag} install \
+ DESTDIR=$RPM_BUILD_ROOT
+
+install -d $RPM_BUILD_ROOT%{_bindir}
+install -p bin/curl_* $RPM_BUILD_ROOT%{_bindir}
+# PLD requires an explicit interpreter path, not /usr/bin/env.
+%{__sed} -i -e '1s,^#!.*env bash,#!/bin/bash,' $RPM_BUILD_ROOT%{_bindir}/curl_*
+
+# libcurl.m4 is the stock curl autoconf macro and conflicts with curl-devel.
+%{__rm} $RPM_BUILD_ROOT%{_datadir}/aclocal/libcurl.m4
+
+# Move the curl headers into a private directory to avoid clashing with
+# curl-devel, and point the pkg-config/config files at it.
+install -d $RPM_BUILD_ROOT%{_includedir}/curl-impersonate
+mv $RPM_BUILD_ROOT%{_includedir}/curl \
+ $RPM_BUILD_ROOT%{_includedir}/curl-impersonate/curl
+%{__sed} -i -e 's,^includedir=.*,includedir=%{_includedir}/curl-impersonate,' \
+ $RPM_BUILD_ROOT%{_pkgconfigdir}/libcurl-impersonate.pc
+%{__sed} -i -e 's,^includedir=.*,includedir="%{_includedir}/curl-impersonate",' \
+ $RPM_BUILD_ROOT%{_bindir}/curl-impersonate-config
+
+%{__rm} $RPM_BUILD_ROOT%{_libdir}/libcurl-impersonate.la
+%{__rm} $RPM_BUILD_ROOT%{_libdir}/libcurl-impersonate.a
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post libs -p /sbin/ldconfig
+%postun libs -p /sbin/ldconfig
+
+%files
+%defattr(644,root,root,755)
+%doc README.md docs/install.rst docs/fingerprints.rst
+%attr(755,root,root) %{_bindir}/curl-impersonate
+%attr(755,root,root) %{_bindir}/curl_*
+%attr(755,root,root) %{_bindir}/wcurl-impersonate
+
+%files libs
+%defattr(644,root,root,755)
+%{_libdir}/libcurl-impersonate.so.*.*.*
+%ghost %{_libdir}/libcurl-impersonate.so.4
+
+%files devel
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/curl-impersonate-config
+%{_libdir}/libcurl-impersonate.so
+%{_includedir}/curl-impersonate
+%{_pkgconfigdir}/libcurl-impersonate.pc
diff --git a/curl-impersonate-build.patch b/curl-impersonate-build.patch
new file mode 100644
index 0000000..5d325fa
--- /dev/null
+++ b/curl-impersonate-build.patch
@@ -0,0 +1,117 @@
+Adapt upstream's bundled "build everything and statically link it" Makefile to
+PLD packaging. Upstream assumes a distro with no system BoringSSL/nghttp2 and
+with libraries under plain "lib"; PLD ships system OpenSSL/nghttp2/zlib/... and
+uses "lib64". This patch makes the build:
+
+ * chrome_libs: build & bundle ONLY the fingerprint-critical dependencies that
+ have no usable PLD counterpart - BoringSSL (the TLS fingerprint) and the
+ pinned/patched nghttp2 (1.63; >=1.65 drops the priority flag), ngtcp2 and
+ nghttp3. The unpatched, fingerprint-irrelevant zlib/zstd/brotli/libidn2 are
+ taken from PLD instead of being rebuilt here.
+
+ * boringssl .patched: strip BoringSSL's own -Werror. With the distro hardening
+ flags injected here, GCC 15 emits false-positive -Wrestrict/-Wstringop-
+ overflow (bogus huge bounds) on its audited memcpy paths; -Werror would make
+ them fatal. Real errors still fail the build.
+
+ * boringssl lib64 alias: curl's configure looks for the --with-openssl libs
+ under lib64, but BoringSSL installs into plain lib - symlink lib64 -> lib.
+
+ * curl configure flags: install libs into lib64 (--libdir), skip docs
+ (--disable-docs; avoids both extra tooling and a man-page clash with the
+ system curl package), and take zlib/zstd/brotli/libidn2 from the system
+ (bare --with-*) instead of the no-longer-built bundled copies.
+
+ * pkg-config / CC: list the bundled nghttp2/ngtcp2/nghttp3 .pc dirs first so
+ they win over the system ones, and carry the bundled lib dirs in CC so the
+ "-L" lands at the front of every link (an LDFLAGS "-L" is reordered after the
+ system paths by libtool). This makes curl link the bundled static BoringSSL
+ and nghttp2/ngtcp2/nghttp3 rather than the system shared libraries.
+
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -83,10 +83,7 @@
+ libidn2_static_libs := $(libidn2_install_dir)/lib/libidn2.a
+
+ # Dependencies needed to compile the Chrome version
+-chrome_libs := $(zlib_static_libs) $(zstd_static_libs) $(brotli_static_libs) $(boringssl_static_libs) $(nghttp2_static_libs) $(ngtcp2_static_libs) $(nghttp3_static_libs)
+-ifneq ($(filter linux%,$(host_os)),)
+-chrome_libs += $(libidn2_static_libs)
+-endif
++chrome_libs := $(boringssl_static_libs) $(nghttp2_static_libs) $(ngtcp2_static_libs) $(nghttp3_static_libs)
+
+ # Auto-generate Makefile help.
+ # Borrowed from https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
+@@ -254,6 +251,11 @@
+ # mv boringssl boringssl-$(BORING_SSL_COMMIT)
+ cd boringssl-$(BORING_SSL_COMMIT)/
+ for p in $^; do patch -p1 < $$p; done
++ # GCC 15 emits false-positive -Wrestrict/-Wstringop-overflow (bogus huge
++ # bounds) on boringssl's audited memcpy paths, which its own -Werror turns
++ # fatal. Drop -Werror so they stay non-fatal warnings (real errors still
++ # fail); the distro hardening flags are still applied.
++ sed -i -e '/set(C_CXX_FLAGS/ s/-Werror //' CMakeLists.txt
+ touch .patched
+
+ $(boringssl_static_libs): boringssl-$(BORING_SSL_COMMIT).zip boringssl-$(BORING_SSL_COMMIT)/.patched
+@@ -453,6 +455,12 @@
+
+ # This is a small hack that flags that curl was patched and configured in the "chrome" version
+ $(CURL_VERSION)/.chrome: $(chrome_libs) $(CURL_VERSION).tar.gz $(CURL_VERSION)/.patched
++ # curl's configure appends the platform libdir suffix (lib64 here) when
++ # locating boringssl via --with-openssl, but it installs into plain lib.
++ # Expose a lib64 alias so curl's link tests (e.g. ECH) find the archives.
++ if test -d "$(boringssl_dir)/lib" && ! test -e "$(boringssl_dir)/lib64"; then \
++ ln -s lib "$(boringssl_dir)/lib64"; \
++ fi
+ cd $(CURL_VERSION)
+
+ # Set up the configure flags to curl.
+@@ -463,7 +471,9 @@
+ # https://daniel.haxx.se/blog/2024/01/10/psl-in-curl/
+ { \
+ config_flags="--prefix=@prefix@"; \
+- config_flags="$$config_flags --with-brotli=$(brotli_install_dir)"; \
++ config_flags="$$config_flags --libdir=@libdir@"; \
++ config_flags="$$config_flags --disable-docs"; \
++ config_flags="$$config_flags --with-brotli"; \
+ config_flags="$$config_flags --with-nghttp2=$(nghttp2_install_dir)"; \
+ config_flags="$$config_flags --with-ngtcp2=$(ngtcp2_install_dir)"; \
+ config_flags="$$config_flags --with-nghttp3=$(nghttp3_install_dir)"; \
+@@ -475,12 +485,12 @@
+ config_flags="$$config_flags --without-libidn2"; \
+ ;; \
+ *) \
+- config_flags="$$config_flags --with-libidn2=$(libidn2_install_dir)"; \
++ config_flags="$$config_flags --with-libidn2"; \
+ ;; \
+ esac; \
+ config_flags="$$config_flags --with-openssl=$(boringssl_dir)"; \
+- config_flags="$$config_flags --with-zlib=$(with_zlib)"; \
+- config_flags="$$config_flags --with-zstd=$(with_zstd)"; \
++ config_flags="$$config_flags --with-zlib"; \
++ config_flags="$$config_flags --with-zstd"; \
+ config_flags="$$config_flags --without-librtmp"; \
+ config_flags="$$config_flags --disable-ldap --disable-ldaps"; \
+ config_flags="$$config_flags --without-libpsl"; \
+@@ -520,12 +530,18 @@
+ esac; \
+ }
+
++ # PKG_CONFIG_PATH lists the bundled nghttp2/ngtcp2/nghttp3 first so they win
++ # over the system copies; the system default path is left enabled so curl
++ # finds the system brotli/zstd/zlib/libidn2. CC carries the bundled lib dirs
++ # (static .a only) at the front of every link so the bundled boringssl and
++ # nghttp2/ngtcp2/nghttp3 win over the system shared libraries (an LDFLAGS -L
++ # would be reordered after the system paths by libtool).
+ DYLD_LIBRARY_PATH="$$lib_path" \
+ LD_LIBRARY_PATH="$$lib_path" \
+- PKG_CONFIG_LIBDIR= \
+- PKG_CONFIG_PATH="$(ngtcp2_install_dir)/lib/pkgconfig" \
++ PKG_CONFIG_PATH="$(nghttp2_install_dir)/lib/pkgconfig:$(ngtcp2_install_dir)/lib/pkgconfig:$(nghttp3_install_dir)/lib/pkgconfig" \
+ ./configure \
+ $$config_flags \
++ CC="$(CC) -L$(boringssl_dir)/lib -L$(nghttp2_install_dir)/lib -L$(ngtcp2_install_dir)/lib -L$(nghttp3_install_dir)/lib" \
+ LIBS="$$add_libs"
+
+ # Remove possible leftovers from a previous compilation
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/curl-impersonate.git/commitdiff/c290869f62de8c836dda49345e78b276a57231a6
More information about the pld-cvs-commit
mailing list