impit is a rust library that allows you to impersonate a browser and make requests to websites. It is built on top of reqwest, rustls and tokio and supports HTTP/1.1, HTTP/2, and HTTP/3.
The library provides a simple API for making requests to websites, and it also allows you to customize the request headers, use proxies, custom timeouts and more.
use impit::cookie::Jar;
use impit::{impit::Impit, fingerprint::database as fingerprints};
#[tokio::main]
async fn main() {
let impit = Impit::<Jar>::builder()
.with_fingerprint(fingerprints::firefox_144::fingerprint())
.with_http3()
.build()
.unwrap();
let response = impit
.get(String::from("https://example.com"), None, None)
.await;
match response {
Ok(response) => {
println!("{}", response.text().await.unwrap());
}
Err(e) => {
println!("{:#?}", e);
}
}
}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 | req/s | Wheel | Profiles | Backend |
|---|---|---|---|---|
rnet |
3808 | 3.7 MB | 75 | Rust |
primp |
3547 | 5.3 MB | n/a1 | Rust |
impit |
2885 | 4.3 MB | 20 | Rust |
tls-client |
1831 | 41.3 MB | 51 | Go |
curl_cffi |
1548 | 13.5 MB | 38 | C (libcurl) |
httpx (no impersonation) |
759 | 0.1 MB | — | Python |
Node.js
| Package | req/s | Install | Profiles | Backend |
|---|---|---|---|---|
impit |
1353 | 8.7 MB | 20 | Rust |
got-scraping |
11492 | 5.2 MB | 33 | Node.js TLS |
node-tls-client |
901 | 31.1 MB | 63 | Go |
cycletls |
287 | 133.3 MB | raw JA3 | Go subprocess |
undici (no impersonation) |
2030 | 2.0 MB | — | Node.js |
If you'd prefer to use impit from a Node.js application, check out the impit-node folder, or download the package from npm:
npm install impitThe interface is the same as the native fetch.
import { Impit } from 'impit';
// Set up the Impit instance
const impit = new Impit({
browser: "chrome", // or "firefox"
proxyUrl: "http://localhost:8080",
ignoreTlsErrors: true,
});
// Use the `fetch` method as you would with the built-in `fetch` function
const response = await impit.fetch("https://example.com");
console.log(response.status);
console.log(response.headers);
console.log(await response.text());
// console.log(await response.json());
// ...Technically speaking, the impit project is a somewhat thin wrapper around reqwest that provides a more ergonomic API for making requests to websites.
The real strength of impit is that it uses patched versions of rustls and other libraries that allow it to make browser-like requests.
Note that if you want to use this library in your rust project, you have to add the following dependencies to your Cargo.toml file:
[dependencies]
impit = { git="https://github.com/apify/impit.git", branch="master" }
[patch.crates-io]
rustls = { git="https://github.com/apify/rustls.git" }
h2 = { git="https://github.com/apify/h2.git" }Without the patched dependencies, the project won't build.
Note that you also have to build your project with rustflags = "--cfg reqwest_unstable", otherwise, the build will also fail.
This is because impit uses unstable features of reqwest (namely http3 support), which are not available in the stable version of the library.
Footnotes
-
primpaccepts arbitrary version strings and snaps to the nearest shipped profile, so the set is not enumerable through the public API. ↩ -
Over HTTP/1.1 — with HTTP/2 enabled the server closes the session with
GOAWAYafter roughly a thousand requests. ↩ -
Cipher suite and signature algorithm order only; no control over extension order, GREASE, or HTTP/2
SETTINGS. ↩