From 6518c69d6fa438f506422fc7ae8a2043dcb834a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jind=C5=99ich=20B=C3=A4r?= Date: Wed, 26 Aug 2026 10:49:39 +0200 Subject: [PATCH 1/2] docs: compare impit against other impersonation clients --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index e6304f61..23e0a6b8 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,35 @@ async fn main() { } ``` +### Comparison + +Sequential requests from a single client against a local Node.js HTTP/2 server (1 KiB JSON body, keep-alive), best of 11 runs of 2000 requests, pinned to one core. Profile counts are the distinct versioned impersonation targets exposed by the public API. Numbers are indicative — rerun them on your own hardware before drawing conclusions. + +**Python** + +| Package | Version | req/s | Wheel | Profiles | Backend | +| --- | --- | --- | --- | --- | --- | +| [`rnet`](https://github.com/0x676e67/rnet) | 2.4.2 | 3808 | 3.7 MB | 75 | Rust | +| [`primp`](https://github.com/deedy5/primp) | 1.3.1 | 3547 | 5.3 MB | n/a[^1] | Rust | +| **`impit`** | 0.14.0 | 2885 | 4.3 MB | 20 | Rust | +| [`tls-client`](https://github.com/FlorianREGAZ/Python-Tls-Client) | 1.0.1 | 1831 | 41.3 MB | 51 | Go | +| [`curl_cffi`](https://github.com/lexiforest/curl_cffi) | 0.16.2 | 1548 | 13.5 MB | 38 | C (libcurl) | +| `httpx` (no impersonation) | 0.28.1 | 759 | 0.1 MB | — | Python | + +**Node.js** + +| Package | Version | req/s | Install | Profiles | Backend | +| --- | --- | --- | --- | --- | --- | +| **`impit`** | 0.14.4 | 1353 | 8.7 MB | 20 | Rust | +| [`got-scraping`](https://github.com/apify/got-scraping) | 4.2.1 | 1149[^2] | 5.2 MB | 3[^3] | Node.js TLS | +| [`node-tls-client`](https://github.com/Sahil1337/node-tls-client) | 2.1.0 | 901 | 31.1 MB | 63 | Go | +| [`cycletls`](https://github.com/Danny-Dasilva/CycleTLS) | 2.0.5 | 287 | 133.3 MB | raw JA3 | Go subprocess | +| `undici` (no impersonation) | 8.10.0 | 2030 | 2.0 MB | — | Node.js | + +[^1]: `primp` accepts arbitrary version strings and snaps to the nearest shipped profile, so the set is not enumerable through the public API. +[^2]: Over HTTP/1.1 — with HTTP/2 enabled the server closes the session with `GOAWAY` after roughly a thousand requests. +[^3]: Cipher suite and signature algorithm order only; no control over extension order, GREASE, or HTTP/2 `SETTINGS`. + ### Other projects If you'd prefer to use `impit` from a Node.js application, check out the [`impit-node`](https://github.com/apify/impit/tree/master/impit-node) folder, or download the package from npm: From 1187aed800100d3edfd514436b438504acc0a972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jind=C5=99ich=20B=C3=A4r?= Date: Wed, 26 Aug 2026 11:17:26 +0200 Subject: [PATCH 2/2] docs: drop version column from the comparison matrix --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 23e0a6b8..c8e43ae2 100644 --- a/README.md +++ b/README.md @@ -37,24 +37,24 @@ Sequential requests from a single client against a local Node.js HTTP/2 server ( **Python** -| Package | Version | req/s | Wheel | Profiles | Backend | -| --- | --- | --- | --- | --- | --- | -| [`rnet`](https://github.com/0x676e67/rnet) | 2.4.2 | 3808 | 3.7 MB | 75 | Rust | -| [`primp`](https://github.com/deedy5/primp) | 1.3.1 | 3547 | 5.3 MB | n/a[^1] | Rust | -| **`impit`** | 0.14.0 | 2885 | 4.3 MB | 20 | Rust | -| [`tls-client`](https://github.com/FlorianREGAZ/Python-Tls-Client) | 1.0.1 | 1831 | 41.3 MB | 51 | Go | -| [`curl_cffi`](https://github.com/lexiforest/curl_cffi) | 0.16.2 | 1548 | 13.5 MB | 38 | C (libcurl) | -| `httpx` (no impersonation) | 0.28.1 | 759 | 0.1 MB | — | Python | +| Package | req/s | Wheel | Profiles | Backend | +| --- | --- | --- | --- | --- | +| [`rnet`](https://github.com/0x676e67/rnet) | 3808 | 3.7 MB | 75 | Rust | +| [`primp`](https://github.com/deedy5/primp) | 3547 | 5.3 MB | n/a[^1] | Rust | +| **`impit`** | 2885 | 4.3 MB | 20 | Rust | +| [`tls-client`](https://github.com/FlorianREGAZ/Python-Tls-Client) | 1831 | 41.3 MB | 51 | Go | +| [`curl_cffi`](https://github.com/lexiforest/curl_cffi) | 1548 | 13.5 MB | 38 | C (libcurl) | +| `httpx` (no impersonation) | 759 | 0.1 MB | — | Python | **Node.js** -| Package | Version | req/s | Install | Profiles | Backend | -| --- | --- | --- | --- | --- | --- | -| **`impit`** | 0.14.4 | 1353 | 8.7 MB | 20 | Rust | -| [`got-scraping`](https://github.com/apify/got-scraping) | 4.2.1 | 1149[^2] | 5.2 MB | 3[^3] | Node.js TLS | -| [`node-tls-client`](https://github.com/Sahil1337/node-tls-client) | 2.1.0 | 901 | 31.1 MB | 63 | Go | -| [`cycletls`](https://github.com/Danny-Dasilva/CycleTLS) | 2.0.5 | 287 | 133.3 MB | raw JA3 | Go subprocess | -| `undici` (no impersonation) | 8.10.0 | 2030 | 2.0 MB | — | Node.js | +| Package | req/s | Install | Profiles | Backend | +| --- | --- | --- | --- | --- | +| **`impit`** | 1353 | 8.7 MB | 20 | Rust | +| [`got-scraping`](https://github.com/apify/got-scraping) | 1149[^2] | 5.2 MB | 3[^3] | Node.js TLS | +| [`node-tls-client`](https://github.com/Sahil1337/node-tls-client) | 901 | 31.1 MB | 63 | Go | +| [`cycletls`](https://github.com/Danny-Dasilva/CycleTLS) | 287 | 133.3 MB | raw JA3 | Go subprocess | +| `undici` (no impersonation) | 2030 | 2.0 MB | — | Node.js | [^1]: `primp` accepts arbitrary version strings and snaps to the nearest shipped profile, so the set is not enumerable through the public API. [^2]: Over HTTP/1.1 — with HTTP/2 enabled the server closes the session with `GOAWAY` after roughly a thousand requests.