Skip to content

Asynchronous Rust HTTP Client with TLS, JA3/JA4, and HTTP2 fingerprint spoof any browser

License

Notifications You must be signed in to change notification settings

penumbra-x/rquest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rquest - rust & quest

CI Crates.io License Crates.io MSRV crates.io Crates.io Total Downloads

🚀 Help me work seamlessly with open source sharing by sponsoring me on GitHub

An ergonomic, all-in-one TLS, JA3/JA4, and HTTP2 fingerprint HTTP Client for spoofing any browser.

  • Plain, JSON, urlencoded, multipart bodies
  • Header Order
  • Redirect Policy
  • Cookie Store
  • HTTP Proxies
  • WebSocket Upgrade
  • HTTPS via BoringSSL
  • Perfectly mimic Chrome, Safari, and Firefox

Additional learning resources include:

Usage

This asynchronous example uses Tokio and enables some optional features, so your Cargo.toml could look like this:

HTTP

[dependencies]
tokio = { version = "1", features = ["full"] }
rquest = "1.0.0"
use rquest::{Client, Impersonate};

#[tokio::main]
async fn main() -> Result<(), rquest::Error> {
    // Build a client to mimic Firefox133
    let client = Client::builder()
        .impersonate(Impersonate::Firefox133)
        .build()?;

    // Use the API you're already familiar with
    let resp = client.get("https://tls.peet.ws/api/all").send().await?;
    println!("{}", resp.text().await?);

    Ok(())
}

WebSocket

[dependencies]
tokio = { version = "1", features = ["full"] }
rquest = { version = "1.0.0", features = ["websocket"] }
futures-util = { version = "0.3.0", default-features = false, features = ["std"] }
use futures_util::{SinkExt, StreamExt, TryStreamExt};
use rquest::{Impersonate, Client, Message};

#[tokio::main]
async fn main() -> Result<(), rquest::Error> {
    // Build a client to mimic Firefox133
    let client = Client::builder()
        .impersonate(Impersonate::Firefox133)
        .build()?;

    // Use the API you're already familiar with
    let websocket = client
        .websocket("wss://echo.websocket.org")
        .send()
        .await?
        .into_websocket()
        .await?;

    let (mut tx, mut rx) = websocket.split();

    tokio::spawn(async move {
        for i in 1..11 {
            tx.send(Message::Text(format!("Hello, World! #{i}")))
                .await
                .unwrap();
        }
    });

    while let Some(message) = rx.try_next().await? {
        match message {
            Message::Text(text) => println!("received: {text}"),
            _ => {}
        }
    }

    Ok(())
}

Overview

rquest is a fork of reqwest, and most of the APIs remain the same, similar to how BoringSSL is a fork of OpenSSL.

The fork optimizes commonly used APIs and enhances compatibility with connection pools, making it easier to switch proxies, IP addresses, and interfaces. Projects using reqwest can be migrated to rquest directly with minimal changes.

As synchronous APIs are not actively maintained due to time constraints, only asynchronous APIs are supported. Maintenance may be discontinued in the future; if you find this project helpful, please consider sponsoring me.

Performance

BoringSSL is a fork of OpenSSL that is designed to be more secure and efficient. It is used by Google Chrome and Android, and is also used by Cloudflare. In addition to that, regarding the TLS parrot echo issue in Firefox, we haven’t encountered any serious problems with BoringSSL related to Golang utls issue.

Connection Pool

Regarding the design strategy of the connection pool, rquest and reqwest are implemented differently. rquest reconstructs the entire connection layer, treating each host with the same proxy or bound IP/Interface as the same connection, while reqwest treats each host as an independent connection. Specifically, the connection pool of rquest is managed based on the host and Proxy/IP/Interface, while the connection pool of reqwest is managed only by the host. In other words, when using rquest, you can flexibly switch between proxies, IP or Interface without affecting the management of the connection pool.

Interface refers to the network interface of the device, such as wlan0 or eth0.

Root Certificate

By default, rquest uses Mozilla's root certificates through the webpki-roots crate. This is a static root certificate bundle that is not automatically updated. It also ignores any root certificates installed on the host running rquest, which may be a good thing or a bad thing, depending on your point of view. But you can turn off default-features to cancel the default certificate bundle, and the system default certificate path will be used to load the certificate. In addition, rquest also provides a certificate store for users to customize the update certificate.

Fingerprint

  1. TLS/HTTP2 fingerprint

Supports custom TLS/HTTP2 fingerprint parameters (disabled by default). Unless you’re highly familiar with TLS and HTTP2, customization is not recommended, as it may cause unexpected issues.

  1. JA3/JA4/Akkmai fingerprint

As TLS encryption technology becomes more and more sophisticated and HTTP2 becomes more popular, JA3/JA4/Akkmai fingerprints cannot simulate browser fingerprints very well, and the parsed parameters cannot perfectly imitate the browser's TLS/HTTP2 configuration fingerprints. Therefore, rquest has not planned to support parsing JA3/JA4/Akkmai fingerprint strings for simulation, but encourages users to customize the configuration according to their own situation.

Most of the Akkmai fingerprint strings obtained by users are not fully calculated. For example, the website, where the Headers Frame lacks Priority and Stream ID. If I were the server, it would be easy to detect this. For details, please refer to HTTP2 frame parser

  1. Default fingerprint
Basic device emulation types are provided by default
  • Chrome

Chrome100Chrome101Chrome104Chrome105Chrome106Chrome107Chrome108Chrome109Chrome114Chrome116Chrome117Chrome118Chrome119Chrome120Chrome123Chrome124Chrome126Chrome127Chrome128Chrome129Chrome130Chrome131

  • Edge

Edge101Edge122Edge127Edge131

  • Safari

SafariIos17_2SafariIos17_4_1SafariIos16_5Safari15_3Safari15_5Safari15_6_1Safari16Safari16_5Safari17_0Safari17_2_1Safari17_4_1Safari17_5Safari18SafariIPad18, Safari18_2, Safari18_1_1

  • OkHttp

OkHttp3_9OkHttp3_11OkHttp3_13OkHttp3_14OkHttp4_9OkHttp4_10OkHttp5

  • Firefox

Firefox109, Firefox117, Firefox128, Firefox133

Requirement

Install the environment required to build BoringSSL

Do not compile with crates that depend on OpenSSL; their prefixing symbols are the same and may cause linking failures.

If both OpenSSL and BoringSSL are used as dependencies simultaneously, even if the compilation succeeds, strange issues may still arise.

If you prefer compiling for the musl target, it is recommended to use the tikv-jemallocator memory allocator; otherwise, multithreaded performance may be suboptimal. Only available in version 0.6.0, details: tikv/jemallocator#70

Building

sudo apt-get install build-essential cmake perl pkg-config libclang-dev musl-tools -y

cargo build --release

You can also use this GitHub Actions workflow to compile your project on Linux, Windows, and macOS.

Contributing

If you would like to submit your contribution, please open a Pull Request.

Getting help

Your question might already be answered on the issues

License

Apache-2.0 LICENSE

Accolades

The project is based on a fork of reqwest.