Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Apify Rust client — documentation

This directory documents the public API of the Apify Rust client. The same descriptions are available as rustdoc comments and can be browsed with cargo doc --open.

Note: the cross-file links between these pages (e.g. to actors.md, runs.md, or ../examples/) are written for the repository (GitHub) view. Because the pages are concatenated onto the crate root via include_str! when building rustdoc, those relative links do not resolve in cargo doc output — read the cross-references on GitHub.

Contents

Getting started

Add the crate and an async runtime:

[dependencies]
apify-client = "0.6"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

Some snippets and examples need extra crates: add serde_json = "1" when you read dynamically-typed responses as serde_json::Value (as the README Quick start does), futures-util = "0.3" to consume LogClient::stream() (log streaming — see Store, users and logs), and chrono = "0.4" if you construct or read timestamp values yourself (model timestamp fields are chrono::DateTime<Utc> and chrono is not re-exported, so snippets calling chrono::Utc::now() — such as the monthly_usage and account examples — need it as a direct dependency).

Create a client and call a resource:

use apify_client::ApifyClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = ApifyClient::new("my-api-token");
    let user = client.me().get().await?.expect("account");
    println!("Logged in as {}", user.username.as_deref().unwrap_or("(none)"));
    Ok(())
}

ApifyClient::new takes the API token as an argument — the client does not read it from the environment for you. By convention the token is kept in the APIFY_TOKEN environment variable (this is what every example in examples/ reads, and what the integration-test suite and the Apify platform use), so production code typically does ApifyClient::new(std::env::var("APIFY_TOKEN")?). The literal "my-api-token" above is only a placeholder for brevity.

Imports

The client, the builder, and every option/parameter struct are re-exported at the crate root, so you can import them directly from apify_client — you never need the longer apify_client::clients::<module>::<Type> path. The complete set of re-exported option/parameter types is:

  • Actors: ActorStartOptions, ActorBuildOptions, ActorListOptions
  • Runs: RunListOptions, RunResurrectOptions, RunMetamorphOptions, RunChargeOptions, LastRunOptions
  • Datasets: DatasetListItemsOptions, DatasetDownloadOptions, DownloadItemsFormat
  • Key-value stores: ListKeysOptions, GetRecordOptions
  • Request queues: ListRequestsOptions
  • Store: StoreListOptions
  • Logs: LogOptions
  • Shared: ListOptions, StorageListOptions
  • Client configuration: RequestCompression

plus the common container PaginationList, ListIterator (the return type of every collection client's iterate() method), StoreActorIterator (a type alias for ListIterator<ActorStoreListItem>, the return type of StoreCollectionClient::iterate), and the two cursor-based iterators KeyValueStoreKeysIterator (from KeyValueStoreClient::iterate_keys) and RequestQueueRequestsIterator (from RequestQueueClient::paginate_requests). Import any of them directly from apify_client:

use apify_client::{ApifyClient, ActorListOptions, StoreListOptions, DownloadItemsFormat};

(The apify_client::clients::<module>::<Type> paths shown by cargo doc's module tree also work, but the short crate-root path above is the supported, stable way to import these option types.)

API resource/response models (Actor, ActorRun, Build, Dataset, KeyValueStore, KeyValueStoreKey, KeyValueStoreKeysPage, KeyValueStoreRecord, RequestQueue, RequestQueueRequest, RequestQueueHead, RequestQueueOperationInfo, Task, Schedule, Webhook, WebhookDispatch, ActorStoreListItem, User, …) all live in the apify_client::models module and are imported from there:

use apify_client::models::RequestQueueRequest;

Every model exposes an extra: Extra field that captures any response fields not otherwise modelled; Extra is a type alias for std::collections::HashMap<String, serde_json::Value>, also in apify_client::models. When constructing a model, set extra: Default::default() (an empty map); read passthrough fields from a returned model's extra by key:

use apify_client::models::Extra;

// `extra` is a HashMap<String, serde_json::Value>; look up any passthrough field by key.
fn some_field(extra: &Extra) -> Option<&serde_json::Value> {
    extra.get("someFieldNotModelled")
}

The error type ApifyClientError (and its companions ApiError, ApifyClientResult) is re-exported at the crate root — see Error handling for import and matching:

use apify_client::ApifyClientError;

ApifyClient and the builder

ApifyClient is the entry point. Construct it with ApifyClient::new(token) for the common case, or with ApifyClient::builder() to customize behaviour.

Builder options:

Method Default Description
token(t) none API token, sent as Authorization: Bearer <token>.
base_url(u) https://api.apify.com API origin; /v2 is appended automatically.
public_base_url(u) = base_url Origin used when building public/shareable URLs.
max_retries(n) 8 Maximum retries for 429/5xx/network errors.
min_delay_between_retries(d) 500ms Base backoff delay (doubled each retry, with jitter).
timeout(d) 360s Overall per-request timeout budget.
user_agent_suffix(s) none Extra text appended to the User-Agent header.
request_compression(c) Brotli Encoding for large request bodies: RequestCompression::Brotli (br) or RequestCompression::Gzip (gzip).
http_backend(b) reqwest Replaceable HTTP transport (apify_client::http_client::{HttpBackend, ReqwestBackend}).

Request bodies of at least 1024 bytes are compressed once (before retries) with the selected request_compression algorithm and sent with the matching Content-Encoding header. Brotli is preferred; select gzip for environments or intermediaries that do not handle brotli:

use apify_client::{ApifyClient, RequestCompression};

let client = ApifyClient::builder()
    .token("my-api-token")
    .request_compression(RequestCompression::Gzip)
    .build();

The User-Agent header has the form ApifyClient/{client_version} ({os}; Rust/{rust_version}); isAtHome/{true|false} where the {os} token matches the reference client's os.platform() value (e.g. darwin, win32, linux) so it is identical across all Apify clients, and isAtHome reflects the APIFY_IS_AT_HOME environment variable (the platform variable the reference clients read; rendered lowercase to match them). To reach those values the client maps Rust's native std::env::consts::OS spellings to Node's (macosdarwin, windowswin32, solaris/illumossunos); all other tokens (linux, android, freebsd, …) are already identical and pass through unchanged.

Convenience methods

Beyond the resource accessors, ApifyClient exposes one convenience method:

Method Arguments Returns Description
set_status_message(message, is_terminal) message: &str, is_terminal: bool ActorRun Sets the status message of the current Actor run.

set_status_message updates the run identified by the ACTOR_RUN_ID environment variable, so it only works when called from inside an Actor run. message is the human-readable status text; when is_terminal is true the message becomes final and is not overwritten by later updates. It returns the updated ActorRun, or ApifyClientError::InvalidArgument if ACTOR_RUN_ID is not set.

use apify_client::ApifyClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = ApifyClient::new("my-api-token");
    // Called from inside an Actor run (reads ACTOR_RUN_ID from the environment).
    client.set_status_message("Processing input…", false).await?;
    Ok(())
}

Resource clients

Accessor methods on ApifyClient return resource clients — the collection accessor (plural) lists/creates, and the single-resource accessor (singular) operates on one resource by id:

actors/actor, builds/build, runs/run, tasks/task, datasets/dataset, key_value_stores/key_value_store, request_queues/request_queue, schedules/schedule, webhooks/webhook, webhook_dispatches/webhook_dispatch, store, me/user, log.

Each resource has a dedicated page, linked under Resource clients in the Contents above (Actors, runs, builds, tasks, storages, schedules, webhooks, and store/users/logs).

Iterating collections

A collection's list(...) method returns a single PaginationList page. To walk every item across all pages without tracking offsets yourself, call iterate(...) instead: it returns a lazy ListIterator (re-exported at the crate root) that fetches the next page from the API on demand as you consume items. Every collection client provides it (actors, builds, runs, tasks, datasets, key_value_stores, request_queues, schedules, webhooks, webhook_dispatches, store, and the nested Actor versions/env_vars). DatasetClient exposes iterate_items() for dataset items, and KeyValueStoreClient exposes iterate_keys() for store keys (cursor-based). The options' limit caps the total number of items yielded (unset iterates everything); to control the per-request page size, call .with_chunk_size(n) on the returned iterator (offset-paginated iterators only).

use apify_client::{ApifyClient, ActorListOptions};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = ApifyClient::new("my-api-token");
    let mut actors = client.actors().iterate(ActorListOptions {
        my: Some(true),
        ..Default::default()
    });
    while let Some(actor) = actors.next().await? {
        println!("{}", actor.id);
    }
    Ok(())
}

Error handling

Every fallible method returns Result<T, ApifyClientError>. The variants are:

  • Api(Box<ApiError>) — the API returned a non-success status. ApiError exposes status_code, error_type, message, attempt, http_method, path and optional data.
  • Http(String) — transport/network failure.
  • Timeout — the request exceeded its timeout.
  • Serde(..) — (de)serialization failure.
  • InvalidResponse(..) / InvalidArgument(..) — unexpected response or bad argument.

get/delete map a missing resource to Ok(None) / a no-op.

To inspect the API-level details of an error without matching every variant, use ApifyClientError::as_api_error, which returns Some(&ApiError) for the Api variant and None for any other (transport, timeout, serde, …):

# use apify_client::ApifyClient;
# async fn run() {
# let client = ApifyClient::new("t");
if let Err(err) = client.actor("nonexistent~actor").get().await {
    if let Some(api) = err.as_api_error() {
        eprintln!("API error {}: {}", api.status_code, api.message);
    }
}
# }

Examples

Each example in ../examples is runnable with APIFY_TOKEN=... cargo run --example <name> and is covered by a CI test:

Example Demonstrates
run_store_actor Run a Store Actor, wait, read its default dataset.
storages Create + write + read each storage type.
get_account Fetch the current account, plus its monthly usage (current cycle and for a specific date).
create_build_run_actor Create an Actor, build, run, fetch the run log.
run_and_last_run_storages Run an Actor, then read the last run's storages.
iterate_store Lazily iterate Store Actors.
log_redirection Redirect a separate Actor's run log into your output live, prefixing each line with the source Actor's name.
raw_log Fetch and stream a run's raw (unprocessed) log via LogOptions { raw: Some(true) }.