A high-performance Go client for the qBittorrent Web API with advanced optimizations for cookies and retries.
- Cookie cache: Avoids unnecessary validation requests
- Auto expiration: Cookies are automatically cleared after 24 hours
- Optimized validation: Verify cookies only when needed
- Periodic cleanup: Dedicated goroutine to clear expired cookies
- Exponential backoff: Increasing delay between attempts
- Flexible configuration: Customizable number of retries and delays
- Smart retry: Only for retryable status codes (408, 429, 500, 502, 503, 504)
- Detailed logging: Information about attempts and failures
- Configurable timeouts: Per operation and global
- Context with timeout: Granular control of operations
- Optimized mutexes: RWMutex for better concurrency
- Resource management: Automatic cleanup and memory control
go get github.com/jfxdev/go-qbt
config := qbt.Config{
BaseURL: "http://localhost:8080",
Username: "admin",
Password: "password",
RequestTimeout: 45 * time.Second, // Custom timeout
MaxRetries: 5, // Number of attempts
RetryBackoff: 2 * time.Second, // Base delay between attempts
Debug: false, // Enable debug logging (default: false)
}
Enable debug logging to see detailed information about:
- Login attempts and success
- Cookie expiration events
- Retry attempts with delays
- Operation failures and retries
config := qbt.Config{
BaseURL: "http://localhost:8080",
Username: "admin",
Password: "password",
Debug: true, // Enable verbose logging
}
Note: In production environments, keep Debug: false
to avoid excessive logging.
// Create client
client, err := qbt.New(config)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// List torrents (automatic retry and cookie management)
torrents, err := client.ListTorrents(qbt.ListOptions{})
if err != nil {
log.Printf("Error: %v", err)
}
// Add torrent via magnet link
err = client.AddTorrentLink(qbt.TorrentConfig{
MagnetURI: "magnet:?xt=urn:btih:...",
Directory: "/downloads",
Category: "movies",
Paused: false,
})
if err != nil {
log.Printf("Error adding torrent: %v", err)
}
ListTorrents(opts ListOptions)
- List all torrents with optional filteringAddTorrentLink(opts TorrentConfig)
- Add a torrent via magnet linkPauseTorrents(hash string)
- Pause specific torrentResumeTorrents(hash string)
- Resume specific torrentDeleteTorrents(hash string, deleteFiles bool)
- Delete torrent with optional file deletionIncreaseTorrentsPriority(hash string)
- Increase torrent priorityDecreaseTorrentsPriority(hash string)
- Decrease torrent priorityAddTorrentTags(hash string, tags []string)
- Add tags to torrentDeleteTorrentTags(hash string, tags []string)
- Remove tags from torrentSetCategory(hash string, category string)
- Set torrent categoryRemoveCategory(hash string)
- Remove torrent categoryGetTorrent(hash string)
- Get specific torrent informationGetTorrentProperties(hash string)
- Get detailed torrent propertiesGetTorrentFiles(hash string)
- Get torrent file listGetTorrentTrackers(hash string)
- Get torrent tracker informationGetTorrentPeers(hash string)
- Get torrent peer informationForceRecheck(hash string)
- Force torrent recheckForceReannounce(hash string)
- Force torrent reannounceForceStart(hash string)
- Force start torrentSetTorrentDownloadLimit(hash string, limit int)
- Set torrent download speed limitSetTorrentUploadLimit(hash string, limit int)
- Set torrent upload speed limitSetTorrentShareLimit(hash string, ratioLimit float64, seedingTimeLimit int)
- Set torrent share limits
GetCategories()
- Get all categoriesCreateCategory(name, savePath string)
- Create new categoryDeleteCategory(name string)
- Delete category
GetGlobalSettings()
- Get global qBittorrent settingsSetGlobalSettings(settings GlobalSettings)
- Set global qBittorrent settingsSetDownloadSpeedLimit(limit int)
- Set global download speed limitSetUploadSpeedLimit(limit int)
- Set global upload speed limitToggleSpeedLimits()
- Toggle speed limits mode
GetMainData()
- Get main server data and sync informationGetTransferInfo()
- Get transfer statistics and informationGetNetworkInfo()
- Get network informationGetAppVersion()
- Get qBittorrent application versionGetAPIVersion()
- Get Web API versionGetBuildInfo()
- Get build informationGetLogs(normal, info, warning, critical bool, lastKnownID int)
- Get system logs
GetRSSFeeds(withData bool)
- Get RSS feedsAddRSSFeed(url, path string)
- Add RSS feedRemoveRSSFeed(path string)
- Remove RSS feed
This SDK has been specially optimized for seedbox usage, including essential features for daily management:
- Trackers: Monitor status and performance of all trackers
- Peers: Track connections, speeds and countries of peers
- Logs: Access detailed system logs for debugging
- Network: Monitor network information and DHT connections
- Global Limits: Configure speed limits for download/upload
- Per-Torrent Limits: Individual speed control per torrent
- Ratio Management: Configure ratio limits and seeding time
- Toggle Limits: Quickly enable/disable speed limits
- Categories: Create and manage categories to organize torrents
- Tags: Add and remove tags for better organization
- Paths: Configure specific paths per category
- Global Settings: Access and modify all qBittorrent settings
- RSS Feeds: Configure RSS feeds for download automation
- Recheck/Reannounce: Force checks and announcements when needed
// Monitor tracker performance
trackers, err := client.GetTorrentTrackers("torrent_hash")
if err != nil {
log.Printf("Error getting trackers: %v", err)
}
// Configure ratio limit for seeding
err = client.SetTorrentShareLimit("torrent_hash", 2.0, 168) // 2.0 ratio, 168 hours
if err != nil {
log.Printf("Error configuring ratio: %v", err)
}
// Get system logs for debugging
logs, err := client.GetLogs(true, true, true, true, 0)
if err != nil {
log.Printf("Error getting logs: %v", err)
}
// Configure category for organization
err = client.CreateCategory("movies", "/downloads/movies")
if err != nil {
log.Printf("Error creating category: %v", err)
}
// Global timeout for all operations
config.RequestTimeout = 60 * time.Second
// Retry configuration
config.MaxRetries = 10 // Max attempts
config.RetryBackoff = 1 * time.Second // Base delay
// Cookie settings are automatic:
// - Expiration: 24 hours
// - Check: every 5 minutes
// - Cache: Smart with automatic invalidation
When debug mode is enabled (Debug: true
), the client provides detailed logs for:
- Login attempts and success
- Failures and retries with attempt counts
- Cookie expiration events
- Successful operations after retries
Example debug output:
Login successful, cookies cached
GET /api/v2/torrents/info failed (attempt 1/3), retrying in 2s: authentication error: status code 403
Login successful, cookies cached
GET /api/v2/torrents/info succeeded after 1 retries
Cookies expired, cleared from cache
- Cache hit rate: Cookie cache effectiveness
- Retry statistics: Attempts and failures
- Response times: Per operation
package main
import (
"fmt"
"log"
"time"
"github.com/jfxdev/go-qbt"
)
func main() {
// Configure client
config := qbt.Config{
BaseURL: "http://localhost:8080",
Username: "admin",
Password: "password",
RequestTimeout: 30 * time.Second,
MaxRetries: 3,
RetryBackoff: 2 * time.Second,
Debug: false, // Set to true for verbose logging
}
// Create client
client, err := qbt.New(config)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Get system information
version, err := client.GetAppVersion()
if err != nil {
log.Printf("Error getting version: %v", err)
} else {
fmt.Printf("qBittorrent version: %s\n", version)
}
// List torrents
torrents, err := client.ListTorrents(qbt.ListOptions{})
if err != nil {
log.Printf("Error listing torrents: %v", err)
return
}
fmt.Printf("Found %d torrents\n", len(torrents))
// Add a new torrent
err = client.AddTorrentLink(qbt.TorrentConfig{
MagnetURI: "magnet:?xt=urn:btih:...",
Directory: "/downloads",
Category: "movies",
Paused: false,
})
if err != nil {
log.Printf("Error adding torrent: %v", err)
}
// Get transfer info
info, err := client.GetTransferInfo()
if err != nil {
log.Printf("Error getting transfer info: %v", err)
} else {
fmt.Printf("Download speed: %d bytes/s\n", info.DlSpeed)
fmt.Printf("Upload speed: %d bytes/s\n", info.UpSpeed)
}
}
- Secure cookies: Safe session management
- Timeouts: Prevents hanging operations
- Validation: Automatic credential verification
The client implements robust error handling:
- Automatic retry: For temporary failures with exponential backoff
- Graceful fallback: Elegant degradation on errors
- Smart cookie management: Automatic re-authentication when needed
- Session expiration handling: Detects 401/403 errors and automatically re-authenticates
- Timeout protection: Prevents hanging operations
The client now properly handles qBittorrent session timeouts. When the server returns a 403 (Forbidden) or 401 (Unauthorized) error due to an expired session:
- The client automatically invalidates the cached cookies
- The retry mechanism forces a new login on the next attempt
- The operation is retried seamlessly without user intervention
This fixes the issue where, after several hours, the client would continuously return "forbidden" errors because the qBittorrent Web UI session had expired (configured via WebUISessionTimeout
in qBittorrent settings), while the client still considered its cached cookies as valid.
- Lower latency: Cookie cache avoids re-authentication
- Higher reliability: Automatic retry on temporary failures
- Better performance: Fewer unnecessary requests
- Scalability: Supports multiple concurrent operations
- Maintainability: Cleaner and more organized code
Contributions are welcome! Please open an issue or pull request.
This project is licensed under the GNU General Public License v3.0 - see LICENSE for details.