Quick Start

Add scatter-proxy to your project and start routing requests through SOCKS5 proxies in minutes.

Rust
use scatter_proxy::{
    ScatterProxy, ScatterProxyConfig, RateLimitConfig,
    DefaultClassifier, TaskHandle, ScatterResponse,
};
use std::collections::HashMap;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ScatterProxyConfig {
        sources: vec!["https://example.com/socks5.txt".into()],
        rate_limit: RateLimitConfig {
            default_interval: Duration::from_millis(500),
            host_overrides: HashMap::from([
                ("slow.com".into(), Duration::from_secs(1)),
            ]),
        },
        max_concurrent_per_request: 3,
        state_file: Some("proxy_state.json".into()),
        prefer_remote_dns: true,
        ..Default::default()
    };

    // Build the proxy pool with the default response classifier.
    let pool = ScatterProxy::new(config, DefaultClassifier).await?;

    // Submit a single request.
    let client = reqwest::Client::new();
    let req = client.get("http://httpbin.org/ip").build()?;
    let handle: TaskHandle = pool.submit(req).await;
    let response: ScatterResponse = handle.await;

    // ScatterResponse has: status, headers, body
    println!("Status: {}", response.status);
    println!("Body:   {:?}", response.body);

    // Submit a batch of requests.
    let reqs = vec![
        client.get("http://httpbin.org/ip").build()?,
        client.get("http://httpbin.org/headers").build()?,
        client.get("http://httpbin.org/user-agent").build()?,
    ];
    let handles = pool.submit_batch(reqs).await;
    for h in handles {
        let resp = h.await;
        println!("  → {} ({} bytes)", resp.status, resp.body.len());
    }

    // Check real-time metrics.
    let m = pool.metrics();
    println!(
        "Proxies: {} healthy / {} dead | Success rate: {:.0}%",
        m.healthy_proxies, m.dead_proxies, m.success_rate_1m * 100.0,
    );

    // Graceful shutdown (persists state to disk).
    pool.shutdown().await;

    Ok(())
}