A complete modern rewrite of a Linux tool for recording Spotify audio streams with high quality using PipeWire.
This represents a substantial architectural overhaul with 3x code expansion, featuring modern CLI interface, modular design, and enhanced reliability.
This tool is provided for educational and research purposes only.
- Recording audio from Spotify violates Spotify's Terms of Service and User Guidelines
- Spotify explicitly prohibits "ripping, recording, or copying" content
- Use of this tool may result in Spotify account suspension or termination
- This software is provided AS-IS without warranties of any kind
- Authors are not responsible for any misuse, damages, or consequences
- Users are solely responsible for compliance with applicable laws and terms of service
- Educational study of Linux audio recording techniques
- Testing D-Bus/MPRIS integration and PipeWire audio routing
- Research purposes for understanding audio streaming technology
- Personal backups of content you legally own and have rights to
By using this software, you acknowledge and accept these terms.
- 🎵 Record individual tracks or entire playlists
- 🎚️ High-quality recording (320kbps MP3, 44.1kHz)
- 🔇 Silent recording (no audio output during recording)
- 🏷️ Automatic ID3 metadata tagging
- 🎼 Optional lyrics embedding
- 📋 Playlist support with automatic track management
- 🔄 Skip already-recorded tracks
- 🎛️ PipeWire native (Fedora 42+ optimized)
- Spotify Premium account (320kbps streaming required)
- Linux with PipeWire (Fedora 42+, Ubuntu 24.04+, or Arch)
- Python 3.10+
- Spotify desktop client (flatpak or snap)
| Distribution | Packages |
|---|---|
| Fedora 42+ | pipewire-utils ffmpeg python3-pip playerctl |
| Ubuntu 24.04+ | pipewire-pulse ffmpeg python3-pip playerctl |
| Arch | pipewire ffmpeg python playerctl |
| Distribution | Recommended Method | Command |
|---|---|---|
| Fedora | Flatpak | flatpak install com.spotify.Client |
| Ubuntu | Snap | snap install spotify |
| Arch | AUR | yay -S spotify |
git clone https://github.com/cloudconsultants/spotify-recorder.git
cd spotify-recordercd src
./install.shOr install manually:
Fedora:
sudo dnf install pipewire-utils ffmpeg python3-pip playerctl
flatpak install com.spotify.ClientUbuntu:
sudo apt install pipewire-pulse ffmpeg python3-pip playerctl
snap install spotifyArch:
sudo pacman -S pipewire ffmpeg python playerctl
yay -S spotifyUsing uv (recommended - faster):
curl -LsSf https://astral.sh/uv/install.sh | sh
uv syncOR using pip:
pip install -r requirements.txtIf using flatpak, add to ~/.bashrc:
alias spotify='flatpak run --branch=stable --arch=x86_64 --command=spotify com.spotify.Client'Then reload:
source ~/.bashrc- Visit Spotify Developer Dashboard
- Click "Create app"
- Fill in:
- App name:
Spotify Recorder(or any name) - App description:
Personal audio recorder - Redirect URI:
http://127.0.0.1:8000/callback - Which API/SDKs: Select Web API
- App name:
- Accept Terms of Service → Click Save
- On your app's dashboard, click Settings
- Copy your Client ID
- Click View client secret → Copy your Client Secret
cp .env.example .env
nano .env # or use your preferred editorReplace the placeholder values:
SPOTIFY_CLIENT_ID='your_actual_client_id_here'
SPOTIFY_CLIENT_SECRET='your_actual_client_secret_here'
SPOTIFY_REDIRECT_URI='http://127.0.0.1:8000/callback'On first run, your browser will open for OAuth authorization:
- Log in to Spotify
- Click Agree to authorize
- You'll be redirected to
http://127.0.0.1:8000/callback - The terminal will confirm authorization
Required OAuth Scopes (automatically requested):
user-library-readuser-read-playback-stateuser-read-currently-playing
Settings → Playback:
- ❌ Turn OFF "Crossfade songs"
- ❌ Turn OFF "Automix"
Why: Prevents audio from overlapping between tracks, ensuring clean recordings.
Settings → Audio Quality:
- ✅ Set "Streaming quality" to "Very high" (320kbps)
- ❌ Turn OFF "Auto adjust quality"
- ℹ️ "Normalize volume" can be ON or OFF (personal preference)
Why: 320kbps streaming is required for high-quality recordings. Disabling auto-adjust prevents quality degradation on slow connections.
# Record single track
./spotify-recorder https://open.spotify.com/track/TRACK_ID
# Record entire playlist
./spotify-recorder https://open.spotify.com/playlist/PLAYLIST_ID
# Record album
./spotify-recorder https://open.spotify.com/album/ALBUM_ID
# With verbose logging
./spotify-recorder https://open.spotify.com/track/TRACK_ID --verbosecd src
python3 api.py https://open.spotify.com/track/TRACK_ID./spotify-recorder --help
Options:
--verbose Enable detailed logging
--overwrite Overwrite existing recordings
--update-metadata Update metadata only (skip recording)
--lyrics-mode Add lyrics (none/synced)
--order Track order (first/last/random, default: last*)
--no-record Fetch metadata without recording- Fetch Metadata: Retrieve track info from Spotify Web API
- Start Spotify: Launch desktop client via D-Bus/MPRIS
- Load Track: Use D-Bus
OpenUrito load specific track - Verify Playback: Wait for
PlaybackStatus = "Playing" - Find Audio Sink: Detect Spotify's PipeWire sink-input
- Silent Recording:
- Create null sink for silent output
- Move Spotify to null sink (you hear nothing)
- Record from sink-input with
pw-record
- Convert:
ffmpegconverts raw → MP3 (320kbps) - Tag Metadata: Add ID3 tags and optional lyrics
- Cleanup: Terminate processes, remove temp files
By default, albums/playlist record in reverse order (20→19→18→...→1) for technical reliability:
- Less popular tracks typically have more stable streams
- Preserves API rate limits for important tracks
- Better error recovery if recording fails midway
Use --order first for normal sequence or --order random for shuffle.
PipeWire Recording Settings:
- Format: 32-bit float (
f32) - Sample rate: 44100 Hz (Spotify native)
- Resampler quality: 15 (maximum)
- Bitrate: 320kbps MP3
D-Bus Playback Control:
Player.Play→ Activate devicePlayer.OpenUri→ Load trackPlayer.PlayPause→ Force playbackPlayer.SetPosition→ Seek to 0:00
This tool is untested with Spotify Free accounts. Expected limitations:
| Feature | Free | Premium |
|---|---|---|
| Max Quality | 160kbps | 320kbps |
| Ads | Yes (recorded) | No |
| API Access | Limited | Full |
| Playback Control | May fail | Works |
Recommendation: Use Spotify Premium for reliable recording.
Cause: Spotify not playing or slow internet connection preventing buffering.
Solutions:
- Check Spotify can play audio normally
- Wait for buffering on slow connections (script waits up to 30s)
- Verify:
pactl list sink-inputsshows Spotify while playing
Cause: D-Bus OpenUri not loading correct track.
Solution: Ensure latest version with Play → OpenUri → PlayPause sequence. May require restarting Spotify.
Symptoms: Script warns about snap + flatpak both installed.
Solution:
# Remove snap version (recommended for Fedora):
sudo snap remove spotify
# OR remove flatpak version (recommended for Ubuntu):
flatpak uninstall com.spotify.ClientSymptoms: "Waiting for playback... 0s (state: Paused, track: none)"
Solution: Script waits up to 30s for buffering. Be patient on slow connections. Playback must actually start before recording begins.
spotify-recorder/
├── spotify-recorder # Main executable wrapper
├── README.md # This file
├── LICENSE # MIT License
├── .env.example # Environment template
├── .gitignore # Git exclusions
├── requirements.txt # Pip dependencies
├── pyproject.toml # Modern packaging (uv)
├── src/ # Source code
│ ├── api.py # Main entry point
│ ├── recorder.py # Recording orchestration
│ ├── playback_monitor.py # Playback monitoring
│ ├── utils.py # Utility functions
│ ├── spotdl.sh # Bash recording script
│ └── install.sh # Automated installer
├── docs/ # Documentation
│ └── MODERNIZATION.md # Technical changelog
└── assets/ # Images and resources
├── spotify_settings_0.png
└── spotify_settings_1.png
# Test single track with verbose output:
./spotify-recorder https://open.spotify.com/track/TRACK_ID --verbose
# Dry run (metadata only, no recording):
./spotify-recorder https://open.spotify.com/track/TRACK_ID --no-record# Check Spotify D-Bus interface:
dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify \
/org/mpris/MediaPlayer2 org.freedesktop.DBus.Introspectable.Introspect
# Monitor playback state:
watch -n 1 'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify \
/org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get \
string:org.mpris.MediaPlayer2.Player string:PlaybackStatus'Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
Note: By contributing, you agree that your code will be licensed under the MIT License.
MIT License - see LICENSE file for details.
Disclaimer: This software is provided AS-IS without warranty. Use at your own risk.
- Inspired by original concept from fm16191
- Complete rewrite and modernization by cloudconsultants
- Substantial architectural overhaul with 3x code expansion (636 → 1,667 lines)
- Modern implementation for Fedora 42 + PipeWire (October 2025)
- Uses Spotipy for Spotify Web API
- Uses Mutagen for ID3 tagging

