13 releases

Uses new Rust 2024

1.0.0-rc.1 May 7, 2026
0.5.0 Feb 19, 2026
0.4.3 Jun 16, 2025
0.4.2 Feb 26, 2025
0.2.0 Jul 27, 2023

#4 in Machine learning

Download history 129708/week @ 2026-01-24 152244/week @ 2026-01-31 196148/week @ 2026-02-07 214577/week @ 2026-02-14 271185/week @ 2026-02-21 325531/week @ 2026-02-28 374995/week @ 2026-03-07 329966/week @ 2026-03-14 282487/week @ 2026-03-21 272109/week @ 2026-03-28 307640/week @ 2026-04-04 312700/week @ 2026-04-11 345945/week @ 2026-04-18 396809/week @ 2026-04-25 329640/week @ 2026-05-02 372854/week @ 2026-05-09

1,496,778 downloads per month
Used in 760 crates (357 directly)

Apache-2.0

540KB
10K SLoC

hf-hub

Rust client for the Hugging Face Hub API.

hf-hub provides a typed, ergonomic interface for interacting with the Hugging Face Hub from Rust. It is the Rust equivalent of the Python huggingface_hub library.

Both an async interface (HFClient, on by default) and a synchronous interface (HFClientSync, enabled via the blocking feature) are provided. The two mirror each other method-for-method.

Features

  • Repository operations — query model, dataset, and space metadata; create, delete, update, and move repositories
  • File operations — upload files and folders, download files, list repository trees, check file existence
  • Commit operations — create commits with multiple file operations, list commit history, view diffs between revisions
  • Branch and tag management — create and delete branches and tags, list refs
  • User and organization info — whoami, user profiles, organization details, followers
  • Streaming pagination — async list endpoints return impl Stream<Item = Result<T>> for lazy, memory-efficient iteration; blocking counterparts collect into Vec<T>
  • Bucket operations — create, delete, list, and move buckets; upload, download, and delete files within buckets
  • Xet high-performance transfers — support for Hugging Face's Xet storage backend
  • Async or blocking — use HFClient with your own tokio runtime, or HFClientSync for synchronous callers (requires the blocking feature)

Installation

Add to your Cargo.toml:

[dependencies]
hf-hub = "1.0.0"

To use the synchronous interface, enable the blocking feature:

[dependencies]
hf-hub = { version = "1.0.0", features = ["blocking"] }

CLI Installation

The hfrs command-line tool provides a terminal interface to the Hub. Install it with:

cargo install --git https://github.com/huggingface/hf-hub.git hfrs

This builds in release mode by default. Once installed, run hfrs --help to see available commands.

Quick Start

Async

use hf_hub::HFClient;
use hf_hub::repository::RepoInfo;

#[tokio::main]
async fn main() -> hf_hub::HFResult<()> {
    let client = HFClient::new()?;

    // Get model info
    let RepoInfo::Model(info) = client
        .model("openai-community", "gpt2")
        .info()
        .send()
        .await?
    else {
        unreachable!("handle type guarantees the Model variant");
    };
    println!("Model: {} (downloads: {:?})", info.id, info.downloads);

    Ok(())
}

Blocking

Requires the blocking feature. HFClientSync manages a dedicated tokio runtime internally, so callers do not need their own.

use hf_hub::HFClientSync;
use hf_hub::repository::RepoInfo;

fn main() -> hf_hub::HFResult<()> {
    let client = HFClientSync::new()?;

    let RepoInfo::Model(info) = client
        .model("openai-community", "gpt2")
        .info()
        .send()?
    else {
        unreachable!("handle type guarantees the Model variant");
    };
    println!("Model: {} (downloads: {:?})", info.id, info.downloads);

    Ok(())
}

The blocking handles (HFClientSync, HFRepositorySync, HFSpaceSync, HFBucketSync) mirror their async counterparts method-for-method. See the blocking_* examples in examples/ for runnable programs.

Usage Examples

List models by author

use futures::StreamExt;
use hf_hub::HFClient;

#[tokio::main]
async fn main() -> hf_hub::HFResult<()> {
    let client = HFClient::new()?;

    let stream = client
        .list_models()
        .author("meta-llama")
        .limit(5_usize)
        .send()?;
    futures::pin_mut!(stream);

    while let Some(model) = stream.next().await {
        let model = model?;
        println!("{}", model.id);
    }

    Ok(())
}

Work with a repository handle

use hf_hub::HFClient;
use hf_hub::repository::RepoInfo;

#[tokio::main]
async fn main() -> hf_hub::HFResult<()> {
    let client = HFClient::new()?;
    let repo = client.model("openai-community", "gpt2");

    let RepoInfo::Model(model_info) = repo.info().send().await? else {
        println!("error, not a model");
        return Ok(());
    };
    println!("Model: {}", model_info.id);

    let exists = repo
        .file_exists()
        .filename("config.json")
        .send()
        .await?;

    println!("config.json exists: {exists}");
    Ok(())
}

Download a file

use std::path::PathBuf;
use hf_hub::HFClient;

#[tokio::main]
async fn main() -> hf_hub::HFResult<()> {
    let client = HFClient::new()?;
    let repo = client.model("openai-community", "gpt2");

    let path = repo
        .download_file()
        .filename("config.json")
        .local_dir(PathBuf::from("/tmp/hf-downloads"))
        .send()
        .await?;

    println!("Downloaded to: {}", path.display());
    Ok(())
}

Upload a file

use hf_hub::HFClient;
use hf_hub::repository::AddSource;

#[tokio::main]
async fn main() -> hf_hub::HFResult<()> {
    let client = HFClient::new()?;
    let repo = client.model("your-username", "your-repo");

    let commit = repo
        .upload_file()
        .source(AddSource::Bytes(b"Hello, world!".to_vec()))
        .path_in_repo("greeting.txt")
        .commit_message("Add greeting file")
        .send()
        .await?;

    println!("Committed: {:?}", commit.oid);
    Ok(())
}

Create a repository

use hf_hub::HFClient;

#[tokio::main]
async fn main() -> hf_hub::HFResult<()> {
    let client = HFClient::new()?;

    let url = client
        .create_repo()
        .repo_id("your-username/new-model")
        .private(true)
        .exist_ok(true)
        .send()
        .await?;

    println!("Repository URL: {}", url.url);
    Ok(())
}

Authentication

The client resolves authentication tokens in this order:

  1. Explicit token via HFClientBuilder::token()
  2. HF_TOKEN environment variable
  3. Token file at the path specified by HF_TOKEN_PATH
  4. Default token file at ~/.cache/huggingface/token

Set HF_HUB_DISABLE_IMPLICIT_TOKEN to any non-empty value to disable automatic token resolution.

Configuration

Environment Variable Description
HF_ENDPOINT Hub API endpoint (default: https://huggingface.co)
HF_TOKEN Authentication token
HF_TOKEN_PATH Path to token file
HF_HOME Cache directory root (default: ~/.cache/huggingface)
HF_HUB_DISABLE_IMPLICIT_TOKEN Disable automatic token loading
HF_HUB_USER_AGENT_ORIGIN Custom User-Agent origin string

Error Handling

All fallible operations return Result<T, HFError>. The HFError enum provides structured variants for common failure modes:

  • HFError::AuthRequired — 401 response, token is missing or invalid
  • HFError::RepoNotFound — repository does not exist or is inaccessible
  • HFError::BucketNotFound — bucket does not exist or is inaccessible
  • HFError::EntryNotFound — file or path does not exist in the repository or bucket
  • HFError::RevisionNotFound — branch, tag, or commit does not exist
  • HFError::Forbidden — 403 response, insufficient permissions
  • HFError::Conflict — 409 response, resource already exists or conflicts
  • HFError::RateLimited — 429 response, too many requests
  • HFError::Http — other HTTP errors with status code, URL, and response body

License

Apache-2.0

Dependencies

~34–57MB
~860K SLoC