Skip to main content

flacfetch

PyPI version Python Version Tests codecov License: MIT

flacfetch is a Python tool designed to search for and download high-quality audio files from various sources. It is optimized for finding specific tracks (songs) across both private music trackers and public sources, with intelligent prioritization of "Official" and "Original" releases.

Features

  • Precise Track Search:
    • Private Music Trackers: RED and OPS (API integration). Uses advanced file list filtering to find specific songs within album torrents, downloading only the required track.
    • Streaming Services: Spotify (via librespot, requires Premium account) - CD Quality FLAC (44.1kHz/16-bit).
    • Public Sources: YouTube (via yt-dlp).
  • Smart Prioritization:
    • Official Sources: Automatically prioritizes "Topic" channels and "Official Audio" on YouTube. Spotify results are always from official sources.
    • Quality Heuristics:
      • Trackers (RED/OPS): Prioritizes Lossless (FLAC) and healthy torrents (Seeders). Matches filename exactly to your query.
      • Spotify: CD-quality FLAC (44.1kHz/16-bit) via librespot capture. Prioritizes by popularity.
      • YouTube: Prioritizes newer uploads (Opus codec) over legacy uploads (AAC). Color-codes upload years to help you spot modern, high-quality streams (Green: 2020+, Yellow: 2015-2019, Red: <2015).
  • Flexible Interaction:
    • Interactive Mode: Present search results to the user for manual selection with rich, color-coded metadata (Seeders, Views, Duration).
    • Automatic Mode: Automatically select the highest ranked release.
  • Smart Downloading:
    • Selective BitTorrent: Uses Transmission daemon to download only the specific file matching your search query from larger album torrents (saving bandwidth).
    • Direct Downloads: Handles HTTP/Stream downloads for public sources.

Requirements

  • Python 3.10+
  • requests
  • yt-dlp
  • transmission-rpc
  • Transmission (daemon) - Required for BitTorrent downloads (Optional if only using YouTube)

Installing Transmission

Transmission is a lightweight, cross-platform BitTorrent client with RPC support.

  • Ubuntu/Debian: sudo apt install transmission-daemon
  • macOS: brew install transmission-cli
  • Windows: Download from transmissionbt.com

flacfetch will automatically start the transmission daemon if it's not running.

Installation

From PyPI (Recommended)

pip install flacfetch

From Source

git clone https://github.com/nomadkaraoke/flacfetch.git
cd flacfetch
pip install .

Development Installation

git clone https://github.com/nomadkaraoke/flacfetch.git
cd flacfetch
pip install -e ".[dev]"

Usage

CLI Usage

Standard Search (Artist - Title)

flacfetch "Seether" "Tonight"

Explicit Arguments (Recommended for precision)

flacfetch --artist "Seether" --title "Tonight"

Auto-download Highest Quality

flacfetch --auto --artist "Seether" --title "Tonight"

Output Options

# Specify output directory
flacfetch --artist "Seether" --title "Tonight" -o ~/Music

# Auto-rename to "ARTIST - TITLE.ext"
flacfetch --artist "Seether" --title "Tonight" --rename

# Specify exact filename
flacfetch --artist "Seether" --title "Tonight" --filename "my_song"

# Combine options
flacfetch --artist "Seether" --title "Tonight" -o ~/Music --rename

Verbose Logging

flacfetch -v "Seether" "Tonight"

Configuration

To use private music trackers, you must provide both an API Key and API URL:

# RED
export RED_API_KEY="your_api_key_here"
export RED_API_URL="your_tracker_url_here"
# OR
flacfetch "..." --red-key "your_key" --red-url "your_url"

# OPS
export OPS_API_KEY="your_api_key_here"
export OPS_API_URL="your_tracker_url_here"
# OR
flacfetch "..." --ops-key "your_key" --ops-url "your_url"

Freeleech Tokens (Optional)

Gazelle trackers (RED/OPS) let you spend a Freeleech (FL) token to download a torrent without it counting against your ratio. flacfetch can spend tokens automatically on eligible downloads:

export RED_USE_FL_TOKEN=true      # or: flacfetch "..." --red-use-token
export OPS_USE_FL_TOKEN=true      # or: flacfetch "..." --ops-use-token

Behaviour (opt-in, off by default):

  • Spends a token only when the tracker reports one is spendable for that torrent (its canUseToken flag — which is only true when you currently hold a token, the torrent is ≤ 5 GB, and it isn't already freeleech). This means tokens are used automatically whenever available and it simply stops once you run out.
  • Already-free torrents are never charged a token, and cached .torrent files are reused without spending one.
  • If a token spend fails for any reason, flacfetch transparently falls back to a normal (ratio-counted) download — a failed token never blocks a download.

Note: there is no RED API endpoint that returns your raw token count; the per-torrent canUseToken flag from search results is the authoritative "is a token spendable here" signal, and is what drives this behaviour.

Spotify Configuration (Optional - requires Premium account)

Spotify provides CD-quality audio (44.1kHz/16-bit) captured via librespot and converted to FLAC. This uses the official Spotify Web API for authentication (OAuth) and librespot for audio capture.

Prerequisites:

  • Spotify Premium account
  • librespot binary: brew install librespot or cargo install librespot
  • ffmpeg for audio conversion

Setup:

# 1. Install Spotify extra dependencies
pip install flacfetch[spotify]

# 2. Create a Spotify Developer App
# Go to: https://developer.spotify.com/dashboard
# Click "Create App"
# Set redirect URI to: http://127.0.0.1:8888/callback
# Note your Client ID and Client Secret

# 3. Set environment variables
export SPOTIPY_CLIENT_ID='your-client-id'
export SPOTIPY_CLIENT_SECRET='your-client-secret'
export SPOTIPY_REDIRECT_URI='http://127.0.0.1:8888/callback'

# 4. First run will open browser for OAuth login (token cached automatically)
flacfetch "Artist" "Title"

# Disable Spotify if needed
flacfetch "Artist" "Title" --no-spotify

How it works:

  1. Uses Spotify Web API (via spotipy) for search and playback control
  2. Starts librespot as a Spotify Connect device with OAuth token
  3. Triggers playback via Web API, captures raw PCM via pipe backend
  4. Converts PCM to FLAC using ffmpeg

Note: The redirect URI must use 127.0.0.1 (not localhost) as per Spotify's updated security requirements.

Provider Priority

When multiple providers are configured, flacfetch searches them in priority order. By default: RED > OPS > Spotify > YouTube

This means RED is searched first, and only if it returns no results will OPS be searched, then Spotify, then YouTube. This prioritizes lossless sources first, then high-quality streaming.

# Use default priority (RED > OPS > Spotify > YouTube)
export RED_API_KEY="..."
export RED_API_URL="..."
export OPS_API_KEY="..."
export OPS_API_URL="..."
flacfetch "Artist" "Title" --auto

# Custom priority (e.g., prefer Spotify over trackers)
flacfetch "Artist" "Title" --provider-priority "Spotify,RED,OPS,YouTube"

# Or via environment variable
export FLACFETCH_PROVIDER_PRIORITY="OPS,RED,Spotify,YouTube"
flacfetch "Artist" "Title" --auto

# Disable fallback (only search highest priority provider)
flacfetch "Artist" "Title" --auto --no-fallback

Library Usage

Quick Example:

from flacfetch.core.manager import FetchManager
from flacfetch.core.models import TrackQuery
from flacfetch.providers.red import REDProvider
from flacfetch.providers.ops import OPSProvider
from flacfetch.providers.spotify import SpotifyProvider  # Optional
from flacfetch.downloaders.spotify import SpotifyDownloader  # Optional

manager = FetchManager()
manager.add_provider(REDProvider(api_key="...", base_url="..."))
manager.add_provider(OPSProvider(api_key="...", base_url="..."))

# Spotify (requires SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET, SPOTIPY_REDIRECT_URI env vars)
spotify_provider = SpotifyProvider()
manager.add_provider(spotify_provider)
manager.register_downloader("Spotify", SpotifyDownloader(provider=spotify_provider))

# Search for a specific track
results = manager.search(TrackQuery(artist="Seether", title="Tonight"))
best = manager.select_best(results)

if best:
    # Download returns the path to the downloaded file
    file_path = manager.download(
        best, 
        output_path="./downloads",
        output_filename="Seether - Tonight"  # Optional: custom filename
    )
    print(f"Downloaded to: {file_path}")

For comprehensive library documentation, including:

  • Complete API reference for all classes and methods
  • Data models and type hints
  • Provider configuration options
  • Advanced usage patterns (filtering, custom sorting, batch processing)
  • Error handling best practices
  • 5+ detailed examples

See LIBRARY.md for full library API documentation.

Architecture & Design

See ARCHITECTURE.md for detailed architecture, design choices, and implementation learnings.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Legal Disclaimer

This tool is intended for use with content to which you have legal access. Users are responsible for complying with all applicable laws and terms of service for the supported providers.

License

MIT License - see LICENSE file for details.

Metadata

Release files for flacfetch 0.29.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flacfetch 0.29.0
File Size Uploaded
flacfetch-0.29.0.tar.gz 217.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for flacfetch 0.29.0
File Interpreter ABI Platform
flacfetch-0.29.0-py3-none-any.whl Python 3 none any Details

Total release size: 381.3 kB

Release files / flacfetch-0.29.0.tar.gz

Download URL flacfetch-0.29.0.tar.gz
Size 217.1 kB
Tags Source
SHA-256 checksum
How to use checksums
79b50030a9af2651b51dd2114c459417155381ed12096a59b40578195b5aa3ce
BLAKE2b-256 checksum
How to use checksums
315c9bbf7bfb898cafeac3b802a9debaf3c6839fd20534024b9b31e4ce53c851
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / flacfetch-0.29.0-py3-none-any.whl

Download URL flacfetch-0.29.0-py3-none-any.whl
Size 164.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
787533ddb31f1ef1d39063371bb225aaf82e49393b5aa3a6423aebc99079e102
BLAKE2b-256 checksum
How to use checksums
d9163328a19b215025ed45c084d599a51b1dae70bc6f7742d6ac25c856bce5f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

0.31.0

2 release files

0.30.0

2 release files

This release

0.29.0 This release

2 release files

0.28.1

2 release files

0.28.0

2 release files

0.27.0

2 release files

0.26.0

2 release files

0.25.0

2 release files

0.24.0

2 release files

0.23.0

2 release files

0.22.0

2 release files

0.21.1

2 release files

0.20.2

2 release files

0.20.1

2 release files

0.20.0

2 release files

0.19.6

2 release files

0.19.5

2 release files

0.19.4

2 release files

0.19.3

2 release files

0.18.0

2 release files

0.17.0

2 release files

0.16.2

2 release files

0.16.1

2 release files

0.16.0

2 release files

0.15.1

2 release files

0.15.0

2 release files

0.14.1

2 release files

0.14.0

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.2

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.3

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.4.0

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.1

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page