ElBruno.HuggingFace.Downloader
1.6.1
dotnet add package ElBruno.HuggingFace.Downloader --version 1.6.1
NuGet\Install-Package ElBruno.HuggingFace.Downloader -Version 1.6.1
<PackageReference Include="ElBruno.HuggingFace.Downloader" Version="1.6.1" />
<PackageVersion Include="ElBruno.HuggingFace.Downloader" Version="1.6.1" />
<PackageReference Include="ElBruno.HuggingFace.Downloader" />
paket add ElBruno.HuggingFace.Downloader --version 1.6.1
#r "nuget: ElBruno.HuggingFace.Downloader, 1.6.1"
#:package ElBruno.HuggingFace.Downloader@1.6.1
#addin nuget:?package=ElBruno.HuggingFace.Downloader&version=1.6.1
#tool nuget:?package=ElBruno.HuggingFace.Downloader&version=1.6.1
๐ฅ ElBruno.HuggingFace.Downloader
A .NET library and CLI tool to download files (ONNX models, tokenizers, voice presets, etc.) from Hugging Face Hub repositories with progress reporting, caching, and authentication support.
Project website: elbruno.github.io/ElBruno.HuggingFace.Downloader. See the website guide for publishing and local preview instructions.
Features
- ๐ฆ Download any file from public or private Hugging Face repositories
- ๐ Rich progress reporting with stages (Checking โ Downloading โ Validating โ Complete)
- ๐ HF_TOKEN authentication for gated/private repositories (env var or explicit)
- ๐ Custom Hub endpoints via
HF_ENDPOINTor downloader options - ๐ Atomic writes using temp files to avoid partial/corrupt downloads
- ๐ Resumable downloads using HTTP range requests for interrupted large files
- ๐ Revision pinning with resolved commit metadata and optional expected commit enforcement
- ๐๏ธ Remote file listing โ enumerate files in a repo (models, datasets, spaces) before downloading, no need to know exact paths in advance
- โ Required vs optional files โ optional files fail silently
- ๐งพ Manifest-based bundles with SHA-256 and size validation
- ๐ HEAD requests to resolve total download size before starting
- โญ๏ธ Skip existing files โ only downloads what's missing
- ๐ฅ๏ธ Cross-platform cache directory helpers (Windows, Linux, macOS)
- ๐ DI-friendly with
IServiceCollectionextension methods - ๐ ILogger integration for structured logging
๐ฆ NuGet Packages
| Package | Version | Downloads | Description |
|---|---|---|---|
| ElBruno.HuggingFace.Downloader | Core library for downloading files from Hugging Face Hub repositories | ||
| ElBruno.HuggingFace.Downloader.Cli | CLI tool (hfdownload) for managing Hugging Face downloads |
Installation
Library (NuGet)
dotnet add package ElBruno.HuggingFace.Downloader
.NET Framework
The package also targets netstandard2.0, so it works on .NET Framework 4.6.2 and later. DownloadRequest and the other request types use required and init properties, which need C# 11 or later (the samples below also use collection expressions, so latest is the simplest choice). Passing options or an HttpClient to the HuggingFaceDownloader constructor also needs a reference to System.Net.Http:
<PropertyGroup>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Net.Http" />
</ItemGroup>
CLI Tool
dotnet tool install -g ElBruno.HuggingFace.Downloader.Cli
Once installed, use the hfdownload command:
# Download model files
hfdownload download sentence-transformers/all-MiniLM-L6-v2 onnx/model.onnx tokenizer.json
# Download a specific tag into a revision-aware cache directory
hfdownload download sentence-transformers/all-MiniLM-L6-v2 onnx/model.onnx --revision v1.0
# Restart from scratch instead of resuming a preserved partial download
hfdownload download sentence-transformers/all-MiniLM-L6-v2 onnx/model.onnx --no-resume
# Ensure a manifest-defined bundle with integrity validation
hfdownload download --manifest ./phi4-bundle.json -o ./models/phi4
# Check if files exist locally
hfdownload check sentence-transformers/all-MiniLM-L6-v2 onnx/model.onnx tokenizer.json
# List remote files in a repo without knowing filenames up front
hfdownload files sentence-transformers/all-MiniLM-L6-v2
# List remote files in a dataset repo, as JSON
hfdownload files my-org/my-dataset --repo-type dataset --format json
# List cached models
hfdownload list
# Delete a cached model
hfdownload delete sentence-transformers/all-MiniLM-L6-v2
# See all commands
hfdownload --help
See the full CLI Reference for all commands and options.
Quick Start (Library)
1) Download model files
using ElBruno.HuggingFace;
using var downloader = new HuggingFaceDownloader();
var request = new DownloadRequest
{
RepoId = "sentence-transformers/all-MiniLM-L6-v2",
LocalDirectory = "./models/miniLM",
RequiredFiles = ["onnx/model.onnx", "tokenizer.json"],
OptionalFiles = ["tokenizer_config.json", "vocab.txt"],
Revision = "refs/pr/42"
};
await downloader.DownloadFilesAsync(request);
Console.WriteLine($"Resolved commit: {request.ResolvedCommitSha}");
2) Ensure a manifest-based bundle with SHA-256 validation
var manifest = new ModelBundleManifest
{
RepoId = "microsoft/Phi-4-mini-instruct-onnx",
Revision = "main",
Files =
[
new ModelBundleFile
{
Path = "onnx/model.onnx",
Size = 123456789,
Sha256 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
},
new ModelBundleFile
{
Path = "tokenizer.json",
Required = false
}
]
};
var bundle = await downloader.EnsureBundleAsync(manifest, "./models/phi4");
Console.WriteLine(bundle.ResolvedManifestPath);
Manifest-driven bundle downloads validate existing files before reuse, re-download corrupted files, and write a resolved manifest to ./models/phi4/.hf.bundle.resolved.json.
3) Pin a branch or tag to the expected commit
var request = new DownloadRequest
{
RepoId = "my-org/my-model",
LocalDirectory = "./models/pinned",
RequiredFiles = ["model.onnx"],
Revision = "main",
ExpectedCommitSha = "1234567890abcdef1234567890abcdef12345678"
};
await downloader.DownloadFilesAsync(request);
Console.WriteLine(request.ResolvedCommitSha);
When ExpectedCommitSha is set, the download fails if the resolved commit is missing or differs from the expected SHA. Downloads use the verified immutable commit URL so a moving branch cannot change between verification and transfer. If a custom endpoint or redirect hides revision headers, set Revision to the immutable commit SHA.
4) Check if files are already downloaded
bool ready = downloader.AreFilesAvailable(
["onnx/model.onnx", "tokenizer.json"],
"./models/miniLM");
if (!ready)
{
var missing = downloader.GetMissingFiles(
["onnx/model.onnx", "tokenizer.json"],
"./models/miniLM");
Console.WriteLine($"Missing {missing.Count} files");
}
5) Discover files in a repo before downloading
IReadOnlyList<RepoTreeEntry> entries = await downloader.ListRepoFilesAsync(
"sentence-transformers/all-MiniLM-L6-v2",
RepoType.Model);
foreach (var entry in entries.Where(e => !e.IsDirectory))
Console.WriteLine($"{entry.Path} ({entry.SizeBytes} bytes)");
// Use the discovered paths directly as a download request
await downloader.DownloadFilesAsync(new DownloadRequest
{
RepoId = "sentence-transformers/all-MiniLM-L6-v2",
LocalDirectory = "./models/miniLM",
RequiredFiles = [.. entries.Where(e => !e.IsDirectory).Select(e => e.Path)]
});
6) Track download progress
var progress = new Progress<DownloadProgress>(p =>
{
if (p.Stage == DownloadStage.Downloading)
Console.Write($"\rโฌ๏ธ [{p.CurrentFile}] {p.PercentComplete:F0}% (reused {ByteFormatHelper.FormatBytes(p.ResumedBytes)})");
else
Console.WriteLine($"{p.Stage}: {p.Message}");
});
await downloader.DownloadFilesAsync(new DownloadRequest
{
RepoId = "sentence-transformers/all-MiniLM-L6-v2",
LocalDirectory = "./models/miniLM",
RequiredFiles = ["onnx/model.onnx", "tokenizer.json"],
Progress = progress
});
7) Authentication (Private/Gated Repos)
Set the HF_TOKEN environment variable, or pass it explicitly:
var downloader = new HuggingFaceDownloader(new HuggingFaceDownloaderOptions
{
AuthToken = "hf_your_token_here"
});
8) Use a private Hub endpoint
Set the HF_ENDPOINT environment variable, or configure the endpoint explicitly:
var downloader = new HuggingFaceDownloader(new HuggingFaceDownloaderOptions
{
Endpoint = "https://huggingface.internal"
});
The explicit Endpoint takes precedence over HF_ENDPOINT; if neither is set, the downloader uses https://huggingface.co.
9) Dependency Injection
builder.Services.AddHuggingFaceDownloader(options =>
{
options.Timeout = TimeSpan.FromMinutes(60);
});
// Then inject HuggingFaceDownloader in your services
public class MyModelService(HuggingFaceDownloader downloader)
{
public async Task EnsureModelAsync()
{
await downloader.DownloadFilesAsync(new DownloadRequest
{
RepoId = "my-org/my-model",
LocalDirectory = DefaultPathHelper.GetDefaultCacheDirectory("MyApp"),
RequiredFiles = ["model.onnx", "tokenizer.json"]
});
}
}
9) Manage local cache programmatically
var cacheRoot = DefaultPathHelper.GetDefaultCacheDirectory("hfdownload");
var repoId = "sentence-transformers/all-MiniLM-L6-v2";
// List all cached repositories
var cachedRepos = downloader.ListCachedRepos(cacheRoot);
// Check whether required files are cached for one repo
bool isCached = downloader.IsCached(
repoId,
cacheRoot,
["onnx/model.onnx", "tokenizer.json"]);
// Get total cache size for one local repo directory
long size = downloader.GetCachedSize(
Path.Combine(cacheRoot, DefaultPathHelper.SanitizeModelName(repoId)));
// Delete cached files for the repo (safe no-op if not found)
await downloader.DeleteCachedFilesAsync(repoId, cacheRoot);
Direct downloads also write ./models/.../.hf.download.resolved.json so callers can inspect the requested revision and resolved commit later.
Documentation
| Topic | Description |
|---|---|
| Getting Started | Installation, all usage examples, and setup |
| CLI Reference | Complete CLI command reference |
| API Reference | Complete class and method documentation |
| Architecture | Design decisions, data flow, and project structure |
| Publishing | NuGet publishing with GitHub Actions |
| Website | GitHub Pages deployment, local preview, and website updates |
Related Projects
- ElBruno.PersonaPlex โ Integrates this downloader to auto-download ONNX models for NVIDIA's PersonaPlex-7B-v1 full-duplex speech-to-speech model
Building from Source
git clone https://github.com/elbruno/ElBruno.HuggingFace.Downloader.git
cd ElBruno.HuggingFace.Downloader
dotnet build ElBruno.HuggingFace.Downloader.slnx
dotnet test ElBruno.HuggingFace.Downloader.slnx
Requirements
- .NET 8.0 SDK or later
๐ค Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
๐ License
This project is licensed under the MIT License โ see the LICENSE file for details.
๐ About the Author
Hi! I'm ElBruno ๐งก, a passionate developer and content creator exploring AI, .NET, and modern development practices.
Made with โค๏ธ by ElBruno
If you like this project, consider following my work across platforms:
- ๐ป Podcast: No Tienen Nombre โ Spanish-language episodes on AI, development, and tech culture
- ๐ป Blog: ElBruno.com โ Deep dives on embeddings, RAG, .NET, and local AI
- ๐บ YouTube: youtube.com/elbruno โ Demos, tutorials, and live coding
- ๐ LinkedIn: @elbruno โ Professional updates and insights
- ๐ X: @elbruno โ Quick tips, releases, and tech news
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- System.Text.Json (>= 10.0.5)
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
NuGet packages (14)
Showing the top 5 NuGet packages that depend on ElBruno.HuggingFace.Downloader:
| Package | Downloads |
|---|---|
|
ElBruno.LocalEmbeddings
Local embedding generation using Microsoft.Extensions.AI and ONNX Runtime |
|
|
ElBruno.QwenTTS
Run Qwen3-TTS text-to-speech locally from C# using ONNX Runtime. Models download automatically from HuggingFace on first run. |
|
|
ElBruno.Text2Image
A .NET library for local text-to-image generation using Stable Diffusion and ONNX Runtime. Supports multiple models (SD 1.5, LCM Dreamshaper) with automatic model download from HuggingFace and native C# inference โ no Python dependency. |
|
|
ElBruno.LocalLLMs
Local LLM chat completions using Microsoft.Extensions.AI and ONNX Runtime GenAI. IChatClient implementation for running LLMs locally. |
|
|
ElBruno.VibeVoiceTTS
A .NET library for VibeVoice text-to-speech using ONNX Runtime. Supports automatic model download from HuggingFace, voice presets, and native C# inference with no Python dependency. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.6.1 | 242 | 11/2/2026 |
| 1.6.0 | 213 | 9/28/2026 |
| 1.5.0 | 111 | 9/28/2026 |
| 1.4.4 | 1,673 | 7/27/2026 |
| 1.4.3 | 173 | 7/14/2026 |
| 1.4.2 | 144 | 7/5/2026 |
| 1.4.1 | 132 | 7/5/2026 |
| 1.4.0 | 141 | 7/5/2026 |
| 1.3.0 | 134 | 7/4/2026 |
| 1.2.0 | 138 | 7/4/2026 |
| 1.1.0 | 392 | 4/8/2026 |
| 1.0.0 | 151 | 4/6/2026 |
| 0.6.0 | 19,859 | 2/28/2026 |
| 0.5.0 | 8,033 | 2/23/2026 |