Channels that relied on curated YouTube playlists lose content constantly as videos are removed, age-restricted, or deleted. This tutorial tracks playlist removals daily via Scavio's YouTube playlist endpoint and emits a diff so you can replace removed videos before your viewers notice.
Prerequisites
- Python 3.10+
- A Scavio API key
- A YouTube playlist URL or ID
- SQLite for daily snapshots
Walkthrough
Step 1: Fetch the playlist
Scavio returns all videos with status flags.
import requests, os
API_KEY = os.environ['SCAVIO_API_KEY']
def playlist(pid):
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'youtube_playlist', 'query': pid})
return r.json().get('videos', [])Step 2: Snapshot to SQLite
One row per video per day.
import sqlite3
conn = sqlite3.connect('pl.db')
conn.execute('CREATE TABLE IF NOT EXISTS snap (date TEXT, playlist TEXT, video_id TEXT, title TEXT, status TEXT)')
def snapshot(pid, videos):
for v in videos:
conn.execute('INSERT INTO snap VALUES (date(\'now\'), ?, ?, ?, ?)',
(pid, v['id'], v['title'], v.get('status', 'available')))
conn.commit()Step 3: Diff against yesterday
New removals = yesterday - today.
def diff(pid):
y = set(r[0] for r in conn.execute('SELECT video_id FROM snap WHERE date = date(\'now\', \'-1 day\') AND playlist = ?', (pid,)))
t = set(r[0] for r in conn.execute('SELECT video_id FROM snap WHERE date = date(\'now\') AND playlist = ?', (pid,)))
return y - tStep 4: Alert on removals
Slack or email when removals > 0.
def alert(removed):
if removed:
print(f'ALERT: {len(removed)} videos removed: {list(removed)}')Step 5: Schedule daily run
cron or GitHub Actions at 6am UTC.
0 6 * * * /usr/bin/python3 /path/to/playlist_watch.pyPython Example
import os, requests, sqlite3
API_KEY = os.environ['SCAVIO_API_KEY']
PID = 'PLxxxxxxxx'
conn = sqlite3.connect('pl.db')
conn.execute('CREATE TABLE IF NOT EXISTS snap (date TEXT, video_id TEXT)')
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'youtube_playlist', 'query': PID})
for v in r.json().get('videos', []):
conn.execute('INSERT INTO snap VALUES (date(\'now\'), ?)', (v['id'],))
conn.commit()
print('snapshot saved')JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY;
export async function snap(playlistId) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ platform: 'youtube_playlist', query: playlistId })
});
return (await r.json()).videos;
}Expected Output
Daily diff per playlist, highlighting removed video IDs and titles. Typical finding: 1-5% of a 200-video playlist goes unavailable per month.