Skip to content

Instantly share code, notes, and snippets.

@yowmamasita
Created January 3, 2026 16:48
Show Gist options
  • Select an option

  • Save yowmamasita/40d18bc524c1a840d4ee4b3435945e3b to your computer and use it in GitHub Desktop.

Select an option

Save yowmamasita/40d18bc524c1a840d4ee4b3435945e3b to your computer and use it in GitHub Desktop.
Plex Embedded Poster Fixer - Replaces ugly embedded posters (e.g., from BTM releases with watermarks) with clean TMDB posters
#!/bin/bash
# Plex Embedded Poster Fixer
# Finds movies with embedded posters OR no poster selected, and fixes them with TMDB posters
#
# Usage:
# PLEX_URL="http://localhost:32400" PLEX_TOKEN="your_token" ./fix_embedded_posters.sh
#
# Options:
# PLEX_URL - Your Plex server URL (required)
# PLEX_TOKEN - Your Plex authentication token (required)
# LIBRARY_SECTION - Library section ID to scan (default: 1)
# DRY_RUN - Set to "true" to preview changes without applying (default: false)
set -e
# Validate required environment variables
if [ -z "$PLEX_URL" ]; then
echo "Error: PLEX_URL is required"
echo "Usage: PLEX_URL=\"http://localhost:32400\" PLEX_TOKEN=\"your_token\" $0"
exit 1
fi
if [ -z "$PLEX_TOKEN" ]; then
echo "Error: PLEX_TOKEN is required"
echo "Usage: PLEX_URL=\"http://localhost:32400\" PLEX_TOKEN=\"your_token\" $0"
exit 1
fi
LIBRARY_SECTION="${LIBRARY_SECTION:-1}"
DRY_RUN="${DRY_RUN:-false}"
echo "Plex Embedded Poster Fixer"
echo "=========================="
echo "Server: $PLEX_URL"
echo "Library Section: $LIBRARY_SECTION"
echo "Dry Run: $DRY_RUN"
echo ""
echo "Scanning library..."
# Get all movies in the library
movies=$(curl -s "$PLEX_URL/library/sections/$LIBRARY_SECTION/all?X-Plex-Token=$PLEX_TOKEN" | \
grep -oE 'ratingKey="[0-9]+"' | grep -oE '[0-9]+')
if [ -z "$movies" ]; then
echo "Error: No movies found. Check your PLEX_URL, PLEX_TOKEN, and LIBRARY_SECTION."
exit 1
fi
total=$(echo "$movies" | wc -l | tr -d ' ')
count=0
fixed=0
embedded_count=0
no_selection_count=0
for movie_id in $movies; do
count=$((count + 1))
# Get poster info
poster_info=$(curl -s "$PLEX_URL/library/metadata/$movie_id/posters?X-Plex-Token=$PLEX_TOKEN")
needs_fix=false
reason=""
# Check if embedded poster is selected
if echo "$poster_info" | grep -q 'selected="1".*provider="embedded"'; then
needs_fix=true
reason="embedded"
embedded_count=$((embedded_count + 1))
# Check if NO poster is selected at all (but has embedded available)
elif ! echo "$poster_info" | grep -q 'selected="1"'; then
if echo "$poster_info" | grep -q 'provider="embedded"'; then
needs_fix=true
reason="no_selection_with_embedded"
no_selection_count=$((no_selection_count + 1))
fi
fi
if [ "$needs_fix" = true ]; then
# Get movie title
title=$(curl -s "$PLEX_URL/library/metadata/$movie_id?X-Plex-Token=$PLEX_TOKEN" | \
grep -oE 'title="[^"]*"' | head -1 | sed 's/title="//;s/"$//')
# Get first TMDB poster URL
tmdb_poster=$(echo "$poster_info" | grep -o 'https://image.tmdb.org[^"]*' | head -1)
if [ -n "$tmdb_poster" ]; then
echo "[$count/$total] FIXING ($reason): $movie_id - $title"
if [ "$DRY_RUN" != "true" ]; then
curl -s -X PUT "$PLEX_URL/library/metadata/$movie_id/poster?url=$tmdb_poster&X-Plex-Token=$PLEX_TOKEN" > /dev/null
echo " -> Set to TMDB poster"
else
echo " -> Would set to TMDB poster"
fi
fixed=$((fixed + 1))
else
echo "[$count/$total] WARNING: $movie_id - $title - No TMDB poster available"
fi
fi
# Progress indicator every 100 items
if [ $((count % 100)) -eq 0 ]; then
echo "Progress: $count/$total scanned..."
fi
done
echo ""
echo "=========================="
echo "Done! Scanned $total movies."
echo "Fixed: $fixed posters"
echo " - Embedded posters: $embedded_count"
echo " - No selection (with embedded): $no_selection_count"
if [ "$DRY_RUN" = "true" ]; then
echo ""
echo "This was a dry run. Run without DRY_RUN=true to apply changes."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment