Dave's part of the internet

Not all of this will be relevant. Or even useful.

Soundcloud Streaming

2021-05-22 Dave

I started working on an Alexa skill recently to stream a podcast series from soundcloud. While there is a wealth of developer documentation on the site, this is one of the few services I’ve ever encountered that seems to be intent on crippling developer interactions. Currently developer registrations are closed and most of the existing documentation is filled with information that is no longer valid.

As a result, there are a number of difficulties in trying to find a way to stream from soundcloud. Two main things need to be addressed:

  • a client ID - A hash that authorises requests
  • the streamable url - the address where a track can be streamed from

To get the client ID, I recommend using browser dev tools to find one. Upon opening a soundcloud track, with devtools enabled (hitting F12 on Chrome), check the Network tab and look for one of the many instances with client_id= and copy the hash out:

Request URL: https://api-v2.soundcloud.com/payments/consumer-subscriptions/active?client_id=PAvG20pBVuUJSLH3JkKqSaBje31eHVXu&app_version=1621506060&app_locale=en

specifically:

PAvG20pBVuUJSLH3JkKqSaBje31eHVXu

To get the streamable URL required took a bit more digging and I’ve the following code in python3 to automate the retrieval of the streamable URL from the original soundcloud urls. Once navigated to the soundcloud page via a browser, grab the URL and substitute it for the soundcloud_track_url variable

import requests
import urllib

##############################################
#          Params to update
##############################################
soundcloud_track_url = 'https://soundcloud.com/radio-morpork/night-watch-mid-life-time-crisis'
client_id = 'PAvG20pBVuUJSLH3JkKqSaBje31eHVXu'

##############################################
#          Fixed Strings
##############################################
api_url = 'https://api-v2.soundcloud.com/resolve?url='
client_string_param = '&format=json&client_id='
progressive_media_url = 'NOT FOUND'

# soundcloud URL needs to encoded to append to api request
soundcloud_track_encoded = urllib.parse.quote(soundcloud_track_url, safe='')

# Construct the endpoint to get all the metadata for a soundcloud track
detailed_track_url = api_url + soundcloud_track_encoded + client_string_param + client_id

# Get the json data from that URL
first_request = requests.get(detailed_track_url)
first_request_json = first_request.json()

# Searching the JSON response for a progressive media URL
for transcoding in first_request_json['media']['transcodings']:
    if transcoding['format']['protocol'] == "progressive":
        prog_url = transcoding['url']

# construct the endpoint to get dynamically generated streaming URL
formal_streaming_url = prog_url + '?client_id=' + client_id

# Get the json data from that URL
second_request = requests.get(formal_streaming_url)
second_request_json = second_request.json()

# Get the actual streamable URL for the track
actual_streamable_url = second_request_json['url']

Use the actual_streamable_url parameter at the bottom of the code block above to stream the soundcloud track in whatever player you wish. This is the full URL and can be printed out for validation if needed also.

Hopefully this saves you the few days of suffering I went through to do the same!