[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