Async Rust client for the Apify Cloud API. Run any actor, poll its status, download dataset items — generic over the dataset-item type and with built-in multi-key fallback.
Apify has hundreds of pre-built scrapers ("actors") on their store — Google Maps, LinkedIn, Twitter, e-commerce, you name it. Until now there was no idiomatic Rust client for the API. This crate is the missing piece.
- 🚀 Submit an actor run with arbitrary JSON input.
- ⏳ Poll the run status with configurable interval + timeout.
- 📦 Download dataset items in pages, deserialized straight into your own struct.
- 🔁 Multi-key fallback — supply several Apify tokens; if one runs out of credit, the next is tried automatically.
- 🪵
tracingintegration for structured logging.
[dependencies]
apify-rust-client = "0.1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
serde = { version = "1", features = ["derive"] }use apify_rust_client::{ApifyClient, RunInput};
use serde::Deserialize;
use serde_json::json;
#[derive(Debug, Deserialize)]
struct Place {
title: String,
website: Option<String>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = ApifyClient::new([std::env::var("APIFY_API_KEY")?]);
let input = RunInput::new(json!({
"searchStringsArray": ["coffee shop Berlin"],
"maxCrawledPlacesPerSearch": 20,
}));
let places: Vec<Place> = client
.run_actor("compass~crawler-google-places", input)
.await?
.wait_for_dataset()
.await?;
for p in places {
println!("{} – {:?}", p.title, p.website);
}
Ok(())
}# use apify_rust_client::ApifyClient;
let client = ApifyClient::new([
std::env::var("APIFY_KEY_1").unwrap(),
std::env::var("APIFY_KEY_2").unwrap(),
]);
// First key is tried; on submit failure (e.g. exhausted credit),
// the next key is automatically used.# use apify_rust_client::ApifyClient;
# use std::time::Duration;
let client = ApifyClient::new(["your-key"])
.poll_interval(Duration::from_secs(15)) // default 20s
.max_wait(Duration::from_secs(2 * 60 * 60)); // default 1hAPIFY_API_KEY=apify_api_xxx cargo run --example run_actor| Actor ID | Use case |
|---|---|
compass~crawler-google-places |
Google Maps scraping |
apify~web-scraper |
Generic JS-rendered scraping |
apify~rag-web-browser |
LLM-friendly URL → markdown |
pintostudio~tiktok-scraper |
TikTok |
streamers~linkedin-jobs-scraper |
LinkedIn jobs |
Browse all on apify.com/store.
Apify's free tier gives $5/month in credits. The cost per actor varies (typically $1–10 per 1000 results). With this crate's multi-key fallback you can chain multiple free accounts to extend that budget.
All errors are returned as apify_rust_client::Error:
Error::AllKeysFailed(s)— every supplied key was rejected.Error::RunFailed(s)— actor terminated withFAILED/ABORTED/TIMED-OUT.Error::Timeout(d)— polling exceededmax_wait.Error::ApiStatus { status, body }— non-2xx HTTP response.Error::Http(e)/Error::Json(e)— transport / parsing.
- Sync run endpoint (
/run-sync-get-dataset-items) for short-lived actors - Streaming dataset download (
tokio::Stream) - Webhook builder for completion notifications
- Built-in input validation against actor schema
PRs welcome.
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.