SpawnDev.BlazorJS.WebTorrents brings the amazing WebTorrent library to Blazor WebAssembly.
WebTorrent is a streaming torrent client for node.js and the browser. YEP, THAT'S RIGHT. THE BROWSER. It's written completely in JavaScript – the language of the web – so the same code works in both runtimes.
- 🚀 Streaming torrents in your Blazor WebAssembly applications
- 📦 Full WebTorrent API access through strongly-typed C# wrappers
- 🎬 Stream video and audio directly from torrents
- 📁 Download and seed files entirely in the browser
- 🔄 Real-time progress tracking with events
- 💾 IndexedDB storage support for persistent downloads
- 🎯 Selective file downloading - choose which files to download
- 🌐 WebRTC peer-to-peer connections
- 📊 Statistics and metrics - track download/upload speeds, peer counts, etc.
- 🎨 Intellisense support with comprehensive XML documentation
- .NET 8.0 or later
- Blazor WebAssembly project
- Modern web browser with WebRTC support
- SpawnDev.BlazorJS (automatically installed as a dependency)
dotnet add package SpawnDev.BlazorJS.WebTorrentsOr via Package Manager Console:
Install-Package SpawnDev.BlazorJS.WebTorrentsUpdate your Program.cs to register the required services:
using SpawnDev.BlazorJS;
using SpawnDev.BlazorJS.WebTorrents;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
// Register BlazorJSRuntime (required)
builder.Services.AddBlazorJSRuntime();
// Register WebTorrent service
builder.Services.AddWebTorrentService();
// Initialize BlazorJSRuntime instead of standard RunAsync()
await builder.Build().BlazorJSRunAsync();You can customize WebTorrent behavior with options:
builder.Services.AddWebTorrentService(new WebTorrentOptions
{
DownloadLimit = 50000, // Download speed limit in bytes/sec
Tracker = new TrackerClientOptions
{
// Set default trackers for seeding
Announce = new string[]
{
"wss://tracker.webtorrent.dev",
"wss://tracker.openwebtorrent.com"
},
}
}, webTorrentService =>
{
// Enable verbose logging
webTorrentService.Verbose = true;
});@page "/torrents"
@inject WebTorrentService WebTorrentService
@implements IDisposable
<h3>Torrent Downloader</h3>
@if (torrent != null)
{
<div>
<p>Name: @torrent.Name</p>
<p>Progress: @((torrent.Progress * 100).ToString("F2"))%</p>
<p>Download Speed: @FormatBytes(torrent.DownloadSpeed)/s</p>
<p>Upload Speed: @FormatBytes(torrent.UploadSpeed)/s</p>
<p>Peers: @torrent.NumPeers</p>
</div>
}
@code {
private Torrent? torrent;
protected override async Task OnInitializedAsync()
{
// Wait for WebTorrent to be ready
await WebTorrentService.Ready;
// Add a torrent
var magnetUri = "magnet:?xt=urn:btih:dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c"; // Big Buck Bunny
torrent = WebTorrentService.Client!.Add(magnetUri);
// Subscribe to events
torrent.On("download", () => StateHasChanged());
torrent.On("upload", () => StateHasChanged());
}
private string FormatBytes(double bytes)
{
string[] sizes = { "B", "KB", "MB", "GB" };
int order = 0;
while (bytes >= 1024 && order < sizes.Length - 1)
{
order++;
bytes /= 1024;
}
return $"{bytes:F2} {sizes[order]}";
}
public void Dispose()
{
torrent?.Dispose();
}
}await WebTorrentService.Ready;
var torrent = WebTorrentService.Client!.Add("magnet:?xt=urn:btih:...");
torrent.On("ready", () =>
{
Console.WriteLine($"Torrent ready: {torrent.Name}");
Console.WriteLine($"Files: {torrent.Files.Length}");
});
torrent.On("done", () =>
{
Console.WriteLine("Download complete!");
});await WebTorrentService.Ready;
// Create a torrent from files
using var fileInput = new HTMLInputElement();
fileInput.Type = "file";
fileInput.Multiple = true;
fileInput.Click();
fileInput.OnChange += async () =>
{
var files = fileInput.Files!;
var torrent = WebTorrentService.Client!.Seed(files);
torrent.On("ready", () =>
{
Console.WriteLine($"Seeding: {torrent.MagnetURI}");
});
};await WebTorrentService.Ready;
var torrent = WebTorrentService.Client!.Add(magnetUri);
torrent.On("ready", () =>
{
// Find the video file
var videoFile = torrent.Files.FirstOrDefault(f =>
f.Name.EndsWith(".mp4") || f.Name.EndsWith(".webm"));
if (videoFile != null)
{
// Create a blob URL for the video
var blobUrl = videoFile.StreamURL;
// Use with HTML video element
// <video src="@blobUrl" controls></video>
}
});var torrent = WebTorrentService.Client!.Add(magnetUri, new TorrentOptions
{
// Deselect all files initially
DeselectedFiles = true
});
torrent.On("ready", () =>
{
// Select only specific files to download
foreach (var file in torrent.Files)
{
if (file.Name.EndsWith(".mp4"))
{
file.Select();
}
}
});var torrent = WebTorrentService.Client!.Add(magnetUri);
torrent.On("download", () =>
{
Console.WriteLine($"Progress: {torrent.Progress * 100:F2}%");
Console.WriteLine($"Downloaded: {torrent.Downloaded} bytes");
Console.WriteLine($"Speed: {torrent.DownloadSpeed} bytes/sec");
Console.WriteLine($"Peers: {torrent.NumPeers}");
Console.WriteLine($"Time remaining: {torrent.TimeRemaining} ms");
});// Remove torrent (keeps files)
WebTorrentService.Client!.Remove(torrent);
// Destroy torrent (deletes files)
await torrent.DestroyAsync();The main service for managing torrents.
Key Properties:
Client- The WebTorrent client instanceReady- Task that completes when the service is initializedVerbose- Enable verbose logging
Key Events:
OnTorrentAdd- Fired when a torrent is addedOnTorrentRemove- Fired when a torrent is removedOnTorrentWireAdd- Fired when a peer connection is establishedOnTorrentWireRemove- Fired when a peer connection is closed
Represents a torrent.
Key Properties:
Name- Torrent nameInfoHash- Info hashMagnetURI- Magnet URIFiles- Array of files in the torrentProgress- Download progress (0-1)DownloadSpeed- Current download speed in bytes/secUploadSpeed- Current upload speed in bytes/secDownloaded- Total bytes downloadedUploaded- Total bytes uploadedNumPeers- Number of connected peersReady- True when metadata is loaded
Key Methods:
Select()- Resume downloadingDeselect()- Pause downloadingDestroyAsync()- Destroy torrent and delete filesPause()- Pause the torrentResume()- Resume the torrent
Key Events:
ready- Fired when torrent metadata is readydone- Fired when all files are downloadeddownload- Fired on download progressupload- Fired on upload progresswire- Fired when a new peer connects
Represents a file within a torrent.
Key Properties:
Name- File namePath- File pathLength- File size in bytesDownloaded- Bytes downloadedProgress- Download progress (0-1)StreamURL- Blob URL for streaming
Key Methods:
Select()- Mark file for downloadDeselect()- Exclude file from downloadGetBlobURL()- Get a blob URL for the fileGetBlob()- Get file as a Blob
SpawnDev.BlazorJS.WebTorrents is a collection of JSObject wrappers that provide strongly-typed access to the JavaScript WebTorrent library. The C# API closely mirrors the JavaScript API with full IntelliSense support.
Additional Resources:
WebTorrent (and thus this library) requires WebRTC support. All modern browsers support WebRTC:
- ✅ Chrome/Edge (Chromium-based)
- ✅ Firefox
- ✅ Safari
- ✅ Opera
- Blazor WebAssembly Only: This library only works in Blazor WebAssembly projects. It will not work in Blazor Server.
- Resource Management: Always dispose of
TorrentandFileobjects when done to free up resources. - HTTPS Required: WebRTC requires HTTPS in production environments (localhost works with HTTP during development).
- Storage: Downloaded files are stored in the browser's IndexedDB by default.
Contributions are welcome! Please feel free to submit issues and pull requests at the GitHub repository.
- SpawnDev.BlazorJS - The foundation library for Blazor WebAssembly JavaScript interop
- WebTorrent - The original JavaScript WebTorrent library
This project is licensed under the MIT License - see the LICENSE.txt file for details.
- Built on top of the excellent WebTorrent library
- Powered by SpawnDev.BlazorJS