2026-02-13 12:39:43 +01:00
2026-02-13 12:39:43 +01:00
2026-02-13 11:47:05 +01:00

🎵 Jellyfin Auto-Tagging Script

A Python CLI tool for tagging Jellyfin artists and albums recursively using the Jellyfin API.

📋 Table of Contents

🎯 Overview

This script automates the process of adding tags to Jellyfin music artists and their albums. It's designed to be simple, efficient, and safe, with a dry-run mode to preview changes before applying them.

Features

  • Recursive Tagging: Tags an artist and all their albums with a single command
  • Dry Run Mode: Preview changes without making modifications
  • Tag Preservation: Merges new tags with existing ones (no duplicates)
  • Username/Password Auth: Uses Jellyfin credentials (no API key required)
  • Comprehensive Error Handling: Clear success/failure reporting
  • Minimal Dependencies: Only requires Python and requests library

📦 Requirements

  • Python 3.6+
  • requests library (pip install requests)
  • Jellyfin Server 10.11.5+
  • User account with write permissions

🔧 Installation

1. Clone or Download

# Clone the repository (if available)
git clone https://figureslibres.io/gitea/bachir/jellyfin-tagging
cd jellyfin-tagging

# Or download just the script
wget https://figureslibres.io/gitea/bachir/jellyfin-tagging/raw/branch/master/tag_artist.py
chmod +x tag_artist.py

2. Install Dependencies

pip install requests

3. Make Executable

chmod +x tag_artist.py

🚀 Usage

./tag_artist.py --server SERVER_URL --username USERNAME --password PASSWORD \
               --artist-id ARTIST_ID --tag TAG_NAME [--dry-run]

Command Line Arguments

Argument Required Description Example
--server Yes Jellyfin server URL http://localhost:8096
--username Yes Jellyfin username username
--password Yes Jellyfin password password123
--artist-id Yes Artist ID to tag artistidxxxxxxxxxxxxxxxxxx
--tag Yes Tag to apply yourtag
--dry-run No Dry run mode (no changes) (flag only)

📚 Examples

1. Dry Run (Safe Preview)

./tag_artist.py --server http://10.11.12.13:8096 \
               --username admin \
               --password hBBOmvfsRYvgn0DIfd34 \
               --artist-id b32224387e37aae08d962f71f7272c6c \
               --tag "electronic-favorite" \
               --dry-run

Output:

🎯 Jellyfin Artist Tagger
📡 Server: http://10.11.12.13:8096
👤 Artist ID: b32224387e37aae08d962f71f7272c6c
🏷️  Tag: electronic-favorite
🔄 DRY RUN MODE - No changes will be made

🎵 Fetching artist information...
🎤 Artist: Goldfrapp
🏷️  Tagging artist...
[DRY RUN] Would tag artist 'Goldfrapp' with 'electronic-favorite'
💿 Fetching albums...
📚 Found 10 albums:
[DRY RUN] Would tag album 'Silver Eye' with 'electronic-favorite'
[DRY RUN] Would tag album 'Seventh Tree' with 'electronic-favorite'
...
🎉 Dry run completed! Would tag artist and 10 albums with 'electronic-favorite'

2. Actual Tagging

./tag_artist.py --server http://your.jellyfin.url \
               --username yourusername \
               --password yourpassword \
               --artist-id artistidxxxxxxxxxxxxxx \
               --tag "yourtag"

Output:

🎯 Jellyfin Artist Tagger
📡 Server: http://your.jellyfin.url
👤 Artist ID: artistidxxxxxxxxxxxxxx
🏷️  Tag: yourtag
⚠️  LIVE MODE - Changes will be made

🎵 Fetching artist information...
🎤 Artist: Artist name
🏷️  Tagging artist...
✅ Tagged artist 'Goldfrapp' with 'yourtag'
💿 Fetching albums...
📚 Found 10 albums:
✅ Tagged album 'Album name' with 'yourtag'
✅ Tagged album 'Album name 2' with 'yourtag'
...
🎉 Completed! Tagged artist and 10/10 albums with 'yourtag'

🔍 Technical Details

Authentication

The script uses Jellyfin's username/password authentication to obtain an access token:

# Authentication flow
1. POST to /Users/AuthenticateByName with username/password
2. Receive access token and user ID
3. Use token for all subsequent API calls

API Endpoints Used

  • POST /Users/AuthenticateByName - Authentication
  • GET /Items/{id} - Fetch artist/album details
  • POST /Items/{id} - Update tags

Data Format

The script sends complete artist/album objects matching the Jellyfin UI format:

{
  "Id": "artist-id",
  "Name": "Artist Name",
  "Tags": ["tag1", "tag2"],
  "Genres": ["Genre1", "Genre2"],
  "ProviderIds": {},
  "DateCreated": "2019-01-08T09:19:41.000Z",
  "LockData": false,
  "LockedFields": []
  // ... all other metadata fields
}

Tag Merging Logic

# Preserve existing tags and add new ones
existing_tags = set(current_item.get('Tags', []))
new_tags = set(tags)
merged_tags = list(existing_tags.union(new_tags))

🐛 Troubleshooting

Common Issues

1. Authentication Failed

Error: ❌ Authentication failed: 401 Unauthorized

Solution:

  • Verify username and password
  • Check if user has API access permissions
  • Ensure server URL is correct

2. Artist Not Found

Error: ❌ Could not fetch artist information

Solution:

  • Verify artist ID is correct
  • Check if artist exists in your library
  • Use dry run to test connectivity

3. Tagging Failed

Error: ❌ Failed to tag artist/album

Solution:

  • Check Jellyfin server logs for details
  • Ensure user has write permissions
  • Verify Jellyfin version compatibility

Debugging Tips

  1. Use dry run first: Always test with --dry-run before making changes
  2. Check server logs: Look for detailed error information
  3. Test with different artists: Rule out data-specific issues
  4. Verify network connectivity: Ensure script can reach the server

📜 License

This project is open-source and available under the GNU General Public License v3.0 (GPL-3.0).

See the LICENSE file for the full license text.

👥 Authors

Bach - Initial development and implementation

Mistral AI - Assistance and optimization

🎉 Success Story

This script was developed to automate the tedious process of manually tagging artists and albums in Jellyfin. What started as a simple Python CLI tool evolved into a robust solution that:

  • Successfully tags artists and albums recursively
  • Preserves all existing metadata
  • Provides safe dry-run functionality
  • Handles errors gracefully
  • Matches Jellyfin UI behavior exactly

Result: A production-ready tool that saves hours of manual tagging work! 🎊

📬 Contact

For questions, issues, or contributions, please open an issue on the GitHub repository.

🙏 Acknowledgments

  • Jellyfin team for creating an amazing media server
  • Python community for the excellent requests library
  • All open-source contributors who make tools like this possible

Last Updated: February 13, 2026 Version: 1.0.0

Description
No description provided
Readme GPL-3.0 53 KiB
Languages
Python 100%