#[cfg(feature = "emulation")]
use futures_lite::future::block_on;
#[cfg(feature = "emulation")]
use ugi::{
BoringTlsFingerprint, BrowserFamily, EmulationProfile, Http1Fingerprint, Http2Fingerprint,
};
#[cfg(feature = "emulation")]
fn main() -> Result<(), Box<dyn std::error::Error>> {
block_on(async move {
let profile = EmulationProfile::builder()
.profile_id("custom-api-profile")
.browser_family(BrowserFamily::Custom("api".to_owned()))
.browser_version("1")
.platform("Linux x86_64")
.default_header(
"user-agent",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
)?
.default_header("accept", "*/*")?
.http1_fingerprint(Http1Fingerprint {
header_order: vec![
"host".into(),
"user-agent".into(),
"accept".into(),
"accept-encoding".into(),
],
original_header_case: vec![
("host".into(), "Host".into()),
("user-agent".into(), "User-Agent".into()),
("accept".into(), "Accept".into()),
("accept-encoding".into(), "Accept-Encoding".into()),
],
})
.http2_fingerprint(Http2Fingerprint {
pseudo_header_order: vec![
":method".into(),
":authority".into(),
":scheme".into(),
":path".into(),
],
regular_header_order: vec![
"user-agent".into(),
"accept".into(),
"accept-encoding".into(),
],
..Default::default()
})
.boring_tls_fingerprint(BoringTlsFingerprint {
grease_enabled: Some(true),
permute_extensions: Some(true),
..Default::default()
})
.build();
let client = ugi::Client::builder().emulation(profile).build()?;
let response = client.get("https://api.example.com/health").await?;
println!("status={}", response.status().as_u16());
Ok(())
})
}
#[cfg(not(feature = "emulation"))]
fn main() {
eprintln!(
"This example requires the `emulation` feature:\n cargo run --example emulation_custom --features emulation"
);
}