Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save aluxian/9f90d61a5dbbab832386f69032bcca56 to your computer and use it in GitHub Desktop.
Save aluxian/9f90d61a5dbbab832386f69032bcca56 to your computer and use it in GitHub Desktop.
Export your YouTube liked and disliked videos (.csv)

Script

Create a bash script with the code below as export.sh, give it execution rights with chmod +x export.sh, and run it with your Google access token like so:

./export.sh ya29.a0Ad52N39hmTcEjI1QoL...

Token

Get an access token from: https://developers.google.com/oauthplayground/

https://www.googleapis.com/auth/youtube
https://www.googleapis.com/auth/youtube.channel-memberships.creator
https://www.googleapis.com/auth/youtube.force-ssl
https://www.googleapis.com/auth/youtube.readonly
#!/bin/bash
ratings=("like" "dislike")
auth_token="$1"
csv_file="youtube_api_export.csv"
declare -a existingIds
read_existing_ids() {
if [ -f "$csv_file" ]; then
IFS=$'\n' read -d '' -r -a existingIds < <(tail -n +2 "$csv_file" | cut -d ',' -f 1 | tr -d '"' && printf '\0')
else
echo "CSV file does not exist, creating a new one."
echo "id,title,channelId,channelTitle,publishedAt,description,tags,categoryId,defaultLanguage,defaultAudioLanguage,liveBroadcastContent" > "$csv_file"
fi
echo "Loaded ${#existingIds[@]} existing video IDs."
}
update_csv() {
local items=$1
item_count=$(echo "$items" | jq '.items | length')
echo "Processing $item_count new items..."
local skipped_count=0
local added_count=0
for ((i = 0; i < item_count; i++)); do
local item
item=$(echo "$items" | jq ".items[$i]")
# Extract all snippet fields
local id=$(echo "$item" | jq -r '.id')
local title=$(echo "$item" | jq -r '.snippet.title // empty' | sed 's/"/""/g')
local channelId=$(echo "$item" | jq -r '.snippet.channelId // empty')
local channelTitle=$(echo "$item" | jq -r '.snippet.channelTitle // empty' | sed 's/"/""/g')
local publishedAt=$(echo "$item" | jq -r '.snippet.publishedAt // empty')
local description=$(echo "$item" | jq -r '.snippet.description // empty' | sed 's/"/""/g' | tr '\n' ' ')
local tags=$(echo "$item" | jq -r '.snippet.tags // [] | join(";")' | sed 's/"/""/g')
local categoryId=$(echo "$item" | jq -r '.snippet.categoryId // empty')
local defaultLanguage=$(echo "$item" | jq -r '.snippet.defaultLanguage // empty')
local defaultAudioLanguage=$(echo "$item" | jq -r '.snippet.defaultAudioLanguage // empty')
local liveBroadcastContent=$(echo "$item" | jq -r '.snippet.liveBroadcastContent // empty')
local csvLine="\"$id\",\"$title\",\"$channelId\",\"$channelTitle\",\"$publishedAt\",\"$description\",\"$tags\",\"$categoryId\",\"$defaultLanguage\",\"$defaultAudioLanguage\",\"$liveBroadcastContent\""
if [[ " ${existingIds[*]} " =~ ${id} ]]; then
((skipped_count++))
echo "Skipping existing YouTube video ID: $id"
continue
fi
echo "$csvLine" >> "$csv_file"
((added_count++))
done
echo "Added $added_count new items, skipped $skipped_count items."
}
if [ ! -f "$csv_file" ]; then
echo "id,title,channelId,channelTitle,publishedAt,description,tags,categoryId,defaultLanguage,defaultAudioLanguage,liveBroadcastContent" > "$csv_file"
fi
read_existing_ids
fetch_and_process_videos() {
local rating=$1
local nextPageToken=""
local url="https://www.googleapis.com/youtube/v3/videos?myRating=$rating&maxResults=50&part=snippet&fields=nextPageToken,pageInfo,items(id,snippet(title,channelId,channelTitle,publishedAt,description,tags,categoryId,defaultLanguage,defaultAudioLanguage,liveBroadcastContent))"
while true; do
local requestUrl="${url}"
if [[ -n $nextPageToken ]]; then
requestUrl="${url}&pageToken=${nextPageToken}"
fi
response=$(curl -s --request GET \
--url "$requestUrl" \
--header "Accept: application/json" \
--header "Authorization: Bearer $auth_token" \
--header "User-Agent: insomnia/8.6.1" | jq)
update_csv "$response"
nextPageToken=$(echo "$response" | jq -r '.nextPageToken')
if [[ $nextPageToken == "null" ]] || [[ -z $nextPageToken ]]; then
echo "No more pages to fetch for rating '$rating'."
break
fi
sleep 1
done
}
for rating in "${ratings[@]}"; do
echo "Processing rating: $rating"
fetch_and_process_videos "$rating"
done
echo "CSV file '$csv_file' update complete."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment