Powershell – Spotify API

Published by mail@bewi.at on

To get the a Spotify Token you must create create an App to authorize and get an access token. You can do this on:

https://developer.spotify.com/dashboard/applications

As redirect URI you can enter: http://localhost

This example Powershell Function will return the access token. Also this script checks if there was already an access token (C:\Misc\SpotifyRefreshToken.txt) present and if it will return you a new valid refresh token that will be writen to the SpotifyRefreshToken.txt. This is needed if you don’t run the script on a regulary time (e.g. 60 min). In this case you read the last token and you will get a new refresh token.

Note: On first run you must copy the provided URL to an browser and login with your Spotify credentials. After the login you will get an empty page, but in the URL bar you will find your access token. This token you must copy and enter in the Powershell script prompt.

Function Get-SpotifyToken {

    $RefreshTokenPath = "C:\Misc\SpotifyRefreshToken.txt"
    $RefreshToken = Get-Content $RefreshTokenPath -ErrorAction SilentlyContinue
    Set-Variable -Name SpotifyRefreshToken -Value $RefreshToken -Scope Global

    # Application IDs
    $ClientId = "Your Client ID"
    $ClientSecret = "Your App Secret"

    # Encode to Base64
    $ClientIdBase64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($ClientId))
    # I'dont know why but this works ;-)
    $ClientIdBase64 = $ClientIdBase64.replace("=","6")
    $ClientSecretBase64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($ClientSecret))
    $ClientAppBase64 = $ClientIdBase64 + $ClientSecretBase64

    # Header/Body (Read Only)
    $HeaderGetToken =  @{'Authorization' = 'Basic ' + $ClientAppBase64}

    # If a Refresh Token is saved get new access token
    $Result = Invoke-RestMethod -Uri "https://accounts.spotify.com/api/token" -Method POST -Headers $HeaderGetToken -Body @{grant_type="refresh_token";refresh_token="$SpotifyRefreshToken"} -ErrorAction SilentlyContinue
    If ($Result)
    {
        Set-Variable -Name SpotifyAccessToken -Value $Result.access_token -Scope Global
        Set-Variable -Name SpotifyAccessTokenDateExpires -Value (Get-Date).AddSeconds(3540) -Scope Global
    }

    if (-Not $SpotifyAccessToken) {

        $URLAuthenticate = "https://accounts.spotify.com/en/authorize"
        $ResponseType = "code"
        $RedirectURI = "http://localhost"
        # Scope - App Permissions
        $Scope = "playlist-modify-private playlist-modify-public"

        $URI = $URLAuthenticate + "?client_id=" + $ClientId + "&response_type=" + $ResponseType + "&redirect_uri=" + $RedirectURI + "&scope=" + $Scope
        Write-Host ""
        Write-Host $URI -ForegroundColor Yellow
        Write-Host ""
        $CodeUser = Read-Host "Please enter the URL in a Browser and copy the code from the url bar here"

        $Body = @{'grant_type' = "authorization_code"; 'code' = $CodeUser; 'redirect_uri' = "http://localhost"}
        $Result = Invoke-RestMethod -Uri "https://accounts.spotify.com/api/token" -Method POST -Headers $HeaderGetToken -Body $Body

        Set-Variable -Name SpotifyAccessToken -Value $Result.access_token -Scope Global
        Set-Variable -Name SpotifyRefreshToken -Value $Result.refresh_token -Scope Global
        Set-Content -Path $RefreshTokenPath -Value $SpotifyRefreshToken -Force
        Set-Variable -Name SpotifyAccessTokenDateExpires -Value (Get-Date).AddSeconds(3540) -Scope Global
    }

    If ((Get-Date) -gt $SpotifyAccessTokenDateExpires)
    {
        $Result = Invoke-RestMethod -Uri "https://accounts.spotify.com/api/token" -Method POST -Headers $HeaderGetToken -Body @{grant_type="refresh_token";refresh_token="$SpotifyRefreshToken"}
        If ($Result)
        {
            Set-Variable -Name SpotifyAccessToken -Value $Result.access_token -Scope Global
            Set-Variable -Name SpotifyAccessTokenDateExpires -Value (Get-Date).AddSeconds(3540) -Scope Global
        }
    }

    return $SpotifyAccessToken
}

Now it’s time for an example what you can do. First of all save the above script to some locatain. E.g. C:\SpotifyAPI\Get-SpotifyToken.ps1

As you can see we import the Get-SpotifyToken.ps1 so we can call the function Get-SpotifyToken.

At the bottom you see the Function Script. Lets call it Get-Spotify-Functions.ps1 This is also an Module that you can import in the final script.

# Load the Spotify API Function
. C:\SpotifyAPI\Get-SpotifyToken.ps1

# Start the function to get a access token (The access token will be set in the current Powershell Console as a global variable -> See: Get-SpotifyToken.ps1)
Get-SpotifyToken
$Header =  @{'Authorization' = 'Bearer ' + $SpotifyAccessToken}

# Create a new Spotify Playlist
function New-Spotify-Playlist() {
    Param(
        [string]$Name,
        [switch]$Public
        )

        # Create Playlist
        if ($Public) {
            $Body = @{'name' = $Name; 'public' = 'true' }
        } else {
            $Body = @{'name' = $Name; 'public' = 'false' }
        }
        try {
            $Playlist = Invoke-RestMethod -Uri "https://api.spotify.com/v1/users/benedikt.winder/playlists" -Method Post -Headers $Header -Body ($Body | ConvertTo-JSON)
        }
        catch {
            $LogError = $_.Exception.Message
        }
        
        $PlaylistID = $Playlist.id
        return $PlaylistID
}

# Search the Spotify Library
function Search-Spotify-Library() {
    Param(
        [string]$Artist,
        [string]$Title
        )

    # Create Search Filter
    [uri]$URI = "https://api.spotify.com/v1/search?q=artist:"+$Artist+"+track:"+$Title+"&type=track&limit=1"
    $Tracks = Invoke-RestMethod -Uri $URI -Method Get -Headers $Header
    
    # Get First Track
    try {
        [array]$TrackID = $Tracks.tracks.items.uri
    }
    catch {
        $LogError = $_.Exception.Message
    }
    return $TrackID
}

# Add a track to a playlist.
function Add-Spotify-Track {
    param (
        [array]$TrackID,
        [string]$PlaylistID
    )
    [uri]$URI = "https://api.spotify.com/v1/playlists/"+$PlaylistID+"/tracks"
    $Body = @{'uris' = $TrackID}
    try {
        Invoke-RestMethod -Uri $URI -Method Post -Headers $Header -Body ($Body | ConvertTo-JSON)
    }
    catch {
        $LogError = $_.Exception.Message
    }
}

And now the final script.

# Load Functions
. C:\SpotifyAPI\Get-SpotifyToken.ps1
. C:\SpotifyAPI\Get-Spotify-Functions.ps1

# Create a new playlist
$PlaylistName = "Some cool playlist"
$PlaylistID = New-Spotify-Playlist -Name $PlaylistName -Public

# Search for a song / artist and the TrackID
$Atrist = "Machine Head"
$Track = "Locust"
[array]$TrackID = Search-Spotify-Library -Artist $Artist -Title $Title

# If an TrackID is returnen add it to a playlist / For multiple results you must create a foreach loop
if ($TrackID) {
    Add-Spotify-Track -TrackID $TrackID -PlaylistID $PlaylistID
}
Categories: APISpotify

1 Comment

Mike · September 2, 2021 at 14:31

Hi!

Should this

# Encode to Base64
$ClientIdBase64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($ClientId))

# I’dont know why but this works 😉
$ClientIdBase64 = $ClientIdBase64.replace(“=”,”6″)
$ClientSecretBase64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($ClientSecret))
$ClientAppBase64 = $ClientIdBase64 + $ClientSecretBase64

… not rather be this?

# Encode to Base64
$ClientAppBase64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($ClientId + “:” + $ClientSecret))

Works fine in my tests.

Cheers,
Mike

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

This site uses Akismet to reduce spam. Learn how your comment data is processed.