Rust Client

Rust Client

The Evomi Rust Client provides a production-ready, async interface to Evomi’s API with full type safety and idiomatic Rust patterns.


Installation

Add to your Cargo.toml:

[dependencies]
evomi-client = "0.1.2"
tokio = { version = "1", features = ["full"] }

Quick Start

use evomi_client::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize with API key (or set EVOMI_API_KEY env var)
    let client = Client::new("your-api-key", None, None)?;
    
    // Scrape a URL
    let result = client.scrape("https://example.com", None).await?;
    println!("{:?}", result);
    
    Ok(())
}

Authentication

Set your API key via environment variable:

export EVOMI_API_KEY="your-api-key"

Or pass it directly:

let client = Client::new("your-api-key", None, None)?;

Custom base URL (for testing):

let client = Client::new("your-api-key", Some("https://custom.evomi.com".to_string()), None)?;

Scraping Operations

scrape(url, options)

Scrape a single URL with configurable options.

use evomi_client::{Client, ScrapeOptions};

let result = client.scrape("https://example.com", Some(ScrapeOptions {
    mode: Some("auto".to_string()),
    content: Some("markdown".to_string()),
    device: Some("windows".to_string()),
    proxy_type: Some("residential".to_string()),
    proxy_country: Some("US".to_string()),
    proxy_session_id: Some("abc123".to_string()),
    wait_until: Some("domcontentloaded".to_string()),
    ai_enhance: Some(true),
    ai_prompt: Some("Extract product data".to_string()),
    ai_source: Some("markdown".to_string()),
    js_instructions: Some(vec![serde_json::json!({"click": ".load-more"})]),
    execute_js: Some("window.scrollTo(0, document.body.scrollHeight)".to_string()),
    wait_seconds: Some(2),
    screenshot: Some(false),
    pdf: Some(false),
    excluded_tags: Some(vec!["nav".to_string(), "footer".to_string()]),
    excluded_selectors: Some(vec![".ads".to_string()]),
    block_resources: Some(vec!["image".to_string(), "stylesheet".to_string()]),
    capture_headers: Some(true),
    async_mode: Some(false),
    config_id: Some("cfg_abc123".to_string()),
    scheme_id: Some("sch_abc123".to_string()),
    extract_scheme: Some(vec![serde_json::json!({"label": "title", "type": "content", "selector": "h1"})]),
    storage_id: Some("stor_abc123".to_string()),
    use_default_storage: Some(false),
    
    webhook: None,
    ..Default::default()
})).await?;
Field Type Default Description
mode Option<String> "auto" Scraping mode: "request", "browser", "auto"
content Option<String> "markdown" Output format: "html", "markdown", "screenshot", "pdf"
device Option<String> "windows" Device type: "windows", "macos", "android"
proxy_type Option<String> "residential" Proxy type: "datacenter", "residential"
proxy_country Option<String> "US" Two-letter country code
proxy_session_id Option<String> — Proxy session ID (6-8 chars)
wait_until Option<String> "domcontentloaded" Wait condition
ai_enhance Option<bool> false Enable AI extraction
ai_prompt Option<String> — Prompt for AI extraction
ai_source Option<String> — AI source
ai_force_json Option<bool> true Force AI response to JSON
js_instructions Option<Vec<Value>> — JS actions
execute_js Option<String> — Raw JavaScript to execute
wait_seconds Option<u32> 0 Seconds to wait after page load
screenshot Option<bool> false Capture screenshot
pdf Option<bool> false Capture PDF
excluded_tags Option<Vec<String>> — HTML tags to remove
excluded_selectors Option<Vec<String>> — CSS selectors to remove
block_resources Option<Vec<String>> — Resource types to block
additional_headers Option<HashMap<String, String>> — Extra HTTP headers
capture_headers Option<bool> false Capture response headers
network_capture Option<Vec<Value>> — Network capture filters
async_mode Option<bool> false Return immediately with task ID
config_id Option<String> — Saved config ID
scheme_id Option<String> — Saved extraction schema ID
extract_scheme Option<Vec<Value>> — Inline extraction schema
storage_id Option<String> — Storage config ID
use_default_storage Option<bool> false Use default storage
delivery Option<String> "json" Response format: "raw" or "json"
include_content Option<bool> true Include content in response
webhook Option<WebhookConfig> — Webhook configuration

crawl(domain, options)

Crawl a website to discover and scrape multiple pages.

use evomi_client::CrawlOptions;

let result = client.crawl("example.com", Some(CrawlOptions {
    max_urls: Some(100),
    depth: Some(2),
    url_pattern: Some("/blog/.*".to_string()),
    scraper_config: Some(serde_json::json!({"mode": "browser", "output": "markdown"})),
    async_mode: Some(false),
    webhook: None,
})).await?;
Field Type Default Description
max_urls Option<u32> 100 Maximum URLs to crawl
depth Option<u32> 2 Crawl depth
url_pattern Option<String> — Regex pattern to filter URLs
scraper_config Option<Value> — Config for scraping each page
async_mode Option<bool> false Return immediately with task ID

map_website(domain, options)

Discover URLs from a website via sitemaps, CommonCrawl, or crawling.

use evomi_client::MapOptions;

let result = client.map_website("example.com", Some(MapOptions {
    sources: Some(vec!["sitemap".to_string(), "commoncrawl".to_string()]),
    max_urls: Some(500),
    url_pattern: Some("/products/.*".to_string()),
    check_if_live: Some(false),
    depth: Some(1),
    async_mode: Some(false),
    webhook: None,
})).await?;
Field Type Default Description
sources Option<Vec<String>> ["sitemap", "commoncrawl"] Discovery sources
max_urls Option<u32> 500 Maximum URLs to discover
url_pattern Option<String> — Regex pattern to filter URLs
check_if_live Option<bool> false Check if URLs are live
depth Option<u32> 1 Crawl depth if using crawl source
async_mode Option<bool> false Return immediately with task ID

search_domains(query, options)

Find domains by searching the web.

use evomi_client::SearchOptions;

// Single query
let result = client.search_domains("e-commerce platforms", Some(SearchOptions {
    max_urls: Some(20),
    region: Some("us-en".to_string()),
    webhook: None,
})).await?;

// Multiple queries (up to 10)
let result = client.search_domains(
    vec!["web scraping tools".to_string(), "data extraction".to_string()],
    Some(SearchOptions { max_urls: Some(20), ..Default::default() })
).await?;
Field Type Default Description
max_urls Option<u32> 20 Max domains per query (max: 100)
region Option<String> "us-en" Region for results

agent_request(message)

Send a natural language request to the AI agent.

let result = client.agent_request("Scrape example.com and extract all product prices").await?;

get_task_status(task_id, task_type)

Check the status of an async task.

let result = client.get_task_status("abc123", "scrape").await?;
// task_type: "scrape" | "crawl" | "map" | "config_generate" | "schema"

Config Management

Save and reuse scrape configurations.

list_configs(options)

use evomi_client::ListOptions;

let configs = client.list_configs(Some(ListOptions {
    page: Some(1),
    per_page: Some(20),
    sort_by: Some("created_at".to_string()),
    sort_order: Some("desc".to_string()),
})).await?;

create_config(name, config)

let config = client.create_config("Product Scraper", serde_json::json!({
    "mode": "browser",
    "output": "markdown"
})).await?;

get_config(config_id)

let config = client.get_config("cfg_abc123").await?;

update_config(config_id, name, config)

let config = client.update_config("cfg_abc123", Some("New Name"), Some(serde_json::json!({
    "mode": "request"
}))).await?;

delete_config(config_id)

let result = client.delete_config("cfg_abc123").await?;

generate_config(name, prompt)

Generate a scrape config from natural language using AI.

let config = client.generate_config(
    "Amazon Scraper",
    "Scrape product title and price from Amazon product pages"
).await?;

Schema Management

Define reusable structured data extraction schemas.

list_schemas(options)

let schemas = client.list_schemas(Some(ListOptions {
    page: Some(1),
    per_page: Some(20),
    sort_by: Some("created_at".to_string()),
    sort_order: Some("desc".to_string()),
})).await?;

create_schema(name, config, options)

use evomi_client::CreateSchemaOptions;

let schema = client.create_schema("Product Schema", serde_json::json!({
    "url": "https://example.com/product",
    "extract_scheme": [
        {"label": "title", "type": "content", "selector": "h1"},
        {"label": "price", "type": "content", "selector": ".price"}
    ]
}), Some(CreateSchemaOptions {
    test: Some(true),
    fix: Some(false),
    extract_prompt: None,
})).await?;

get_schema(scheme_id)

let schema = client.get_schema("sch_abc123").await?;

update_schema(scheme_id, name, config, options)

let schema = client.update_schema("sch_abc123", "Updated Schema", serde_json::json!({
    "url": "...",
    "extract_scheme": [...]
}), Some(CreateSchemaOptions {
    test: Some(true),
    ..Default::default()
})).await?;

delete_schema(scheme_id)

let result = client.delete_schema("sch_abc123").await?;

get_schema_status(scheme_id)

let status = client.get_schema_status("sch_abc123").await?;

Schedule Management

Run scrape configs on a recurring schedule.

list_schedules(options, active_only)

let schedules = client.list_schedules(Some(ListOptions {
    page: Some(1),
    per_page: Some(20),
    ..Default::default()
}), Some(false)).await?;

create_schedule(name, config_id, interval_minutes, options)

use evomi_client::CreateScheduleOptions;

let schedule = client.create_schedule(
    "Daily Price Check",
    "cfg_abc123",
    1440,  // Daily (in minutes)
    Some(CreateScheduleOptions {
        start_time: Some("09:00".to_string()),
        stop_on_error: Some(true),
        webhook: None,
    })
).await?;

get_schedule(schedule_id)

let schedule = client.get_schedule("sched_abc123").await?;

update_schedule(schedule_id, name, config_id, interval_minutes, stop_on_error)

let schedule = client.update_schedule(
    "sched_abc123",
    Some("New Name"),
    None,
    Some(720),
    None
).await?;

delete_schedule(schedule_id)

let result = client.delete_schedule("sched_abc123").await?;

toggle_schedule(schedule_id)

let result = client.toggle_schedule("sched_abc123").await?;

list_schedule_runs(schedule_id, page, per_page)

let runs = client.list_schedule_runs("sched_abc123", Some(1), Some(20)).await?;

Storage Management

Connect cloud storage to automatically save scrape results.

list_storage_configs()

let configs = client.list_storage_configs().await?;

create_storage_config(name, storage_type, config, options)

use evomi_client::CreateStorageOptions;

// S3-compatible storage
let storage = client.create_storage_config(
    "My S3",
    "s3_compatible",
    serde_json::json!({
        "bucket": "my-bucket",
        "region": "us-east-1",
        "access_key": "...",
        "secret_key": "..."
    }),
    Some(CreateStorageOptions {
        set_as_default: Some(true),
    })
).await?;

// Google Cloud Storage
let storage = client.create_storage_config(
    "My GCS",
    "gcs",
    serde_json::json!({
        "bucket": "my-bucket",
        "credentials_json": "..."
    }),
    None
).await?;

// Azure Blob Storage
let storage = client.create_storage_config(
    "My Azure",
    "azure_blob",
    serde_json::json!({
        "container": "my-container",
        "connection_string": "..."
    }),
    None
).await?;

update_storage_config(storage_id, name, config, set_as_default)

let storage = client.update_storage_config(
    "stor_abc123",
    Some("Renamed Storage"),
    None,
    Some(true)
).await?;

delete_storage_config(storage_id)

let result = client.delete_storage_config("stor_abc123").await?;

Public API

Access proxy credentials and related data.

get_public_api()

Access the Evomi Public API to get proxy credentials and related data.

let data = client.get_public_api().await?;
// Returns proxy credentials and product information

get_proxy_data()

Get detailed information about your proxy products.

let data = client.get_proxy_data().await?;
// Returns: {"products": {"rp": {...}, "sdc": {...}, "mp": {...}}, ...}

get_targeting_options()

Get available targeting parameters for different proxy types.

let options = client.get_targeting_options().await?;

get_scraper_data()

Get information about your Scraper API access.

let data = client.get_scraper_data().await?;

get_browser_data()

Get information about your Browser API access.

let data = client.get_browser_data().await?;

rotate_session(session_id, product)

Force an IP address change for an existing proxy session.

let result = client.rotate_session("abc12345", "rp").await?;
// product: "rpc", "rp", "sdc", "mp"

generate_proxies(product, options)

Generate proxy strings with specific targeting parameters.

use evomi_client::GenerateProxiesOptions;

let proxies = client.generate_proxies("rp", Some(GenerateProxiesOptions {
    countries: Some("US,GB,DE".to_string()),
    city: Some("New York".to_string()),
    session: Some("sticky".to_string()),
    amount: Some(10),
    protocol: Some("http".to_string()),
    lifetime: Some(30),
    adblock: Some(true),
    ..Default::default()
})).await?;
// Returns plain text, one proxy per line

Account Info

get_account_info()

let info = client.get_account_info().await?;
println!("{:?}", info.get("credits_remaining"));

Webhooks

Webhooks allow you to receive notifications when scraping operations complete, fail, or start. Supports Discord, Slack, and custom endpoints.

WebhookConfig

use evomi_client::WebhookConfig;

// Discord webhook
let webhook = WebhookConfig::new("https://discord.com/api/webhooks/...")
    .webhook_type("discord")
    .events(vec!["completed".to_string(), "failed".to_string()]);

// Custom webhook with HMAC signature
let webhook = WebhookConfig::new("https://your-server.com/webhook")
    .webhook_type("custom")
    .events(vec!["completed".to_string()])
    .secret("your-secret-key");

Using Webhooks with Scrape

let webhook = WebhookConfig::new("https://discord.com/api/webhooks/...")
    .webhook_type("discord")
    .events(vec!["completed".to_string(), "failed".to_string()]);

let result = client.scrape("https://example.com", Some(ScrapeOptions {
    mode: Some("browser".to_string()),
    webhook: Some(webhook),
    ..Default::default()
})).await?;

Using Webhooks with Schedules

let webhook = WebhookConfig::new("https://hooks.slack.com/services/...")
    .webhook_type("slack")
    .events(vec!["completed".to_string()]);

let schedule = client.create_schedule(
    "Daily Monitor",
    "cfg_abc123",
    1440,
    Some(CreateScheduleOptions {
        webhook: Some(webhook),
        ..Default::default()
    })
).await?;

Proxy String Builder

Evomi provides a proxy network you can use with any HTTP client. Build proxy strings for reqwest or any other library:

Automatic Proxy Configuration

use evomi_client::types::{ProxyType, ProxyProtocol, ProxyBuildOptions};

// Build a proxy string for US residential proxy
let proxy_string = client.build_proxy_string(
    ProxyType::Residential,
    Some(ProxyBuildOptions::new()
        .country("US")
        .session("abc12345")
        .protocol(ProxyProtocol::Http))
).await?;
println!("{}", proxy_string);
// Output: http://user:[email protected]:1000

Manual Proxy Configuration

use evomi_client::proxy::ProxyConfig;
use evomi_client::types::{ProxyType, ProxyProtocol, ResidentialMode};

let config = ProxyConfig::new()
    .proxy_type(ProxyType::Residential)
    .protocol(ProxyProtocol::Http)
    .country("US")
    .city("New York")
    .credentials("username", "password");

let proxy_string = config.build_proxy_string();

Proxy Configuration Options

Parameter Type Default Description
proxy_type ProxyType Residential Type: Residential, Datacenter, Mobile
protocol ProxyProtocol Http Protocol: Http, Https, Socks5
country String — Two-letter ISO country code (e.g., “US”, “DE”)
city String — City name (spaces replaced with dots)
region String — State/region name
continent String — Continent: africa, asia, europe, north.america, oceania, south.america
isp String — ISP shortcode (e.g., “att”, “comcast”)
session String — Sticky session ID (6-10 alphanumeric chars)
hardsession String — Hard session ID (6-10 alphanumeric chars)
lifetime u32 — Session duration in minutes (max 120)
mode ResidentialMode — Residential mode: Speed, Quality

Expert Settings

Parameter Type Default Description
latency u32 — Max latency in ms
fraudscore u32 — Max fraud score
device String — Device type: “windows”, “unix”, “apple”
activesince u32 — Min connection minutes
asn String — ASN filter
zip String — Zipcode targeting
http3 bool false Enable HTTP3/QUIC
localdns bool false Local DNS resolution
udp bool false UDP support (Enterprise only)
extended bool false Extended pool (cannot combine with other expert filters)

Proxy Endpoints & Ports

Type HTTP HTTPS SOCKS5
Residential rp.evomi.com:1000 rp.evomi.com:1001 rp.evomi.com:1002
Datacenter dcp.evomi.com:2000 dcp.evomi.com:2001 dcp.evomi.com:2002
Mobile mp.evomi.com:3000 mp.evomi.com:3001 mp.evomi.com:3002

Proxy String Format

{protocol}://{username}:{password}_{params}@{endpoint}:{port}

Example: http://user:[email protected]:1000

Proxy Types

Type Endpoint Use Case
Residential rp.evomi.com:1000 Human-like browsing, anti-bot bypass
Datacenter dcp.evomi.com:2000 Fast, high-volume requests
Mobile mp.evomi.com:3000 Highest trust, mobile-specific targets

Error Handling

use evomi_client::Error;

match client.scrape("https://example.com", None).await {
    Ok(result) => println!("{:?}", result),
    Err(Error::MissingApiKey) => eprintln!("API key not set"),
    Err(Error::HttpError(e)) => eprintln!("HTTP error: {}", e),
    Err(Error::JsonError(e)) => eprintln!("JSON error: {}", e),
    Err(Error::ApiError(msg)) => eprintln!("API error: {}", msg),
    Err(e) => eprintln!("Other error: {}", e),
}

Credits & Pricing

All operations consume credits:

Operation Cost
Base request 1 credit
Browser mode 5x multiplier
Residential proxy 2x multiplier
AI enhancement +30 credits
Screenshot/PDF +1 credit each

Credit usage is returned in the result:

println!("{:?}", result.get("_credits_used"));
println!("{:?}", result.get("_credits_remaining"));

Requirements

  • Rust 1.70+
  • Tokio runtime

Resources

Resource Link
crates.io Package crates.io/crates/evomi-client
Evomi Website evomi.com
API Documentation docs.evomi.com

Benefits

  • Async/Await — Built on Tokio for async operations
  • Full API Coverage — All Evomi endpoints supported
  • Type Safe — Strong typing with idiomatic Rust patterns
  • Builder Pattern — Ergonomic configuration with builder methods