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
1,496,778 downloads per month
Used in 760 crates
(357 directly)
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 intoVec<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
HFClientwith your own tokio runtime, orHFClientSyncfor synchronous callers (requires theblockingfeature)
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:
- Explicit token via
HFClientBuilder::token() HF_TOKENenvironment variable- Token file at the path specified by
HF_TOKEN_PATH - 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 invalidHFError::RepoNotFound— repository does not exist or is inaccessibleHFError::BucketNotFound— bucket does not exist or is inaccessibleHFError::EntryNotFound— file or path does not exist in the repository or bucketHFError::RevisionNotFound— branch, tag, or commit does not existHFError::Forbidden— 403 response, insufficient permissionsHFError::Conflict— 409 response, resource already exists or conflictsHFError::RateLimited— 429 response, too many requestsHFError::Http— other HTTP errors with status code, URL, and response body
License
Apache-2.0
Dependencies
~34–57MB
~860K SLoC