VideoHelp Forum




+ Reply to Thread
Results 1 to 14 of 14
  1. Image
    [Attachment 87392 - Click to enlarge]


    i tried to get spoify audio with WidevineProxy2, but failed.

    it seems WidevineProxy2 cannot grab the license url in spotify chrome web.

    so tried with pywidevine with authorization and client-token in python headers, but also failed. it shows "401 Client Error"

    can i get some tips?

    thanks in advance.
    Last edited by ashtaro; 13th Jun 2025 at 06:31.
    Quote Quote  
  2. have sent you PM some hours ago ... read my PM
    Quote Quote  
  3. Originally Posted by lomero View Post
    have sent you PM some hours ago ... read my PM
    can you help me also?
    Quote Quote  
  4. we have wonderful tool shared from **** for that, but at the moment, due to some spoty changes this tool not work

    wait news
    Quote Quote  
  5. Originally Posted by lomero View Post
    we have wonderful tool shared from **** for that, but at the moment, due to some spoty changes this tool not work

    wait news
    you have a github link for it?
    Quote Quote  
  6. Originally Posted by lomero View Post
    we have wonderful tool shared from **** for that, but at the moment, due to some spoty changes this tool not work

    wait news
    No Spotify-specific tools are needed if you want to get the audio file from the web version. Here is a screenshot of Chromium + audio request opened in DevTools + OpenWV output with the key for it (WidevineProxy2 works too). Just make sure you use a CDM from a physical device, because emulated ones are rejected.
    Image Attached Thumbnails Click image for larger version

Name:	spotify.png
Views:	56
Size:	358.9 KB
ID:	87421  

    Quote Quote  
  7. oh yes, you can find all data from network tab. and get the key
    just for some tracks it's possible do this. and easy to do

    no more convenient if your playlist is 100 tracks or more ... for that better use some tools
    however the tool mentioned above, is not available now. so the trick from network tab that's a good suggestion
    Quote Quote  
  8. Originally Posted by ytdlhelp View Post
    Originally Posted by lomero View Post
    we have wonderful tool shared from **** for that, but at the moment, due to some spoty changes this tool not work

    wait news
    No Spotify-specific tools are needed if you want to get the audio file from the web version. Here is a screenshot of Chromium + audio request opened in DevTools + OpenWV output with the key for it (WidevineProxy2 works too). Just make sure you use a CDM from a physical device, because emulated ones are rejected.
    Edit:

    Got it. have a physical device, downloaded it and decrypted it!!!
    Last edited by vitalka; 16th Jun 2025 at 10:39.
    Quote Quote  
  9. Originally Posted by lomero View Post
    have sent you PM some hours ago ... read my PM
    really thank you
    Quote Quote  
  10. Originally Posted by ytdlhelp View Post
    Originally Posted by lomero View Post
    we have wonderful tool shared from **** for that, but at the moment, due to some spoty changes this tool not work

    wait news
    No Spotify-specific tools are needed if you want to get the audio file from the web version. Here is a screenshot of Chromium + audio request opened in DevTools + OpenWV output with the key for it (WidevineProxy2 works too). Just make sure you use a CDM from a physical device, because emulated ones are rejected.
    thanks for your kind advice
    Quote Quote  
  11. spotify api json to hls conversion

    Code:
    for profile in profiles:
        print(profile["mime_type"], profile["max_bitrate"])
        segment_length = encoding["segment_length"]
    
        init = base_url + response_json["initialization_template"].replace("{{profile_id}}", str(profile["id"])).replace("{{file_type}}", profile["file_type"])
    
        start_time = int(encoding["start_time_millis"] / 1000)
        end_time = int(encoding["end_time_millis"] / 1000)
    
        type_name = "audio" if "audio" in profile["mime_type"] else "video"
        codec_name = profile.get("audio_codec") or profile.get("video_codec")
        name = f"{type_name}_{profile["max_bitrate"]}_{codec_name}.m3u8"
    
        with open(name, "w") as f:
            f.writelines(
                [
                    '#EXTM3U\n',
                    '#EXT-X-VERSION:4\n',
                    '#EXT-X-MEDIA-SEQUENCE:0\n',
                    '#EXT-X-PLAYLIST-TYPE:VOD\n',
                    f'#EXT-X-MAP:URI="{init}"\n',
                    f'#EXT-X-TARGETDURATION:{int(round(segment_length)) + 1}\n'
                ]
            )
            for time in range(start_time, end_time, segment_length):
                segment = base_url + response_json["segment_template"].replace("{{profile_id}}", str(profile["id"])).replace("{{file_type}}", profile["file_type"]).replace("{{segment_timestamp}}", str(int(time)))
                f.write(f'#EXTINF:{segment_length}\n')
                f.write(f'{segment}\n')
    
            f.write("#EXT-X-ENDLIST\n")
    
    with open("master.m3u8", "w") as f:
        f.writelines(
            [
                '#EXTM3U\n',
                '#EXT-X-INDEPENDENT-SEGMENTS\n'
            ]
        )
    
        for profile in profiles:
            type_name = "audio" if "audio" in profile["mime_type"] else "video"
            codec_name = profile.get("audio_codec") or profile.get("video_codec")
            name = f"{type_name}_{profile["max_bitrate"]}_{codec_name}"
    
            if type_name == "video":
                f.write(
                    '#EXT-X-STREAM-INF:'
                    f'BANDWIDTH={profile["video_bitrate"]},'
                    f'CODECS="{profile["video_codec"]}",'
                    f'RESOLUTION={f'{profile["video_width"]}x{profile["video_height"]}'},'
                    'AUDIO="default-audio-group"\n'
                )
                f.write(f'{name}.m3u8\n')
            elif type_name == "audio":
                f.write(
                    '#EXT-X-MEDIA:'
                    'TYPE=AUDIO,'
                    f'URI="{name}.m3u8",'
                    'GROUP-ID="default-audio-group",'
                    f'NAME="{name}"\n'
                )
    Bypass HMACs, One-time-tokens and Lic.Wrapping: https://github.com/DevLARLEY/WidevineProxy2
    Quote Quote  
  12. Originally Posted by larley View Post
    spotify api json to hls conversion

    Code:
    for profile in profiles:
        print(profile["mime_type"], profile["max_bitrate"])
        segment_length = encoding["segment_length"]
    
        init = base_url + response_json["initialization_template"].replace("{{profile_id}}", str(profile["id"])).replace("{{file_type}}", profile["file_type"])
    
        start_time = int(encoding["start_time_millis"] / 1000)
        end_time = int(encoding["end_time_millis"] / 1000)
    
        type_name = "audio" if "audio" in profile["mime_type"] else "video"
        codec_name = profile.get("audio_codec") or profile.get("video_codec")
        name = f"{type_name}_{profile["max_bitrate"]}_{codec_name}.m3u8"
    
        with open(name, "w") as f:
            f.writelines(
                [
                    '#EXTM3U\n',
                    '#EXT-X-VERSION:4\n',
                    '#EXT-X-MEDIA-SEQUENCE:0\n',
                    '#EXT-X-PLAYLIST-TYPE:VOD\n',
                    f'#EXT-X-MAP:URI="{init}"\n',
                    f'#EXT-X-TARGETDURATION:{int(round(segment_length)) + 1}\n'
                ]
            )
            for time in range(start_time, end_time, segment_length):
                segment = base_url + response_json["segment_template"].replace("{{profile_id}}", str(profile["id"])).replace("{{file_type}}", profile["file_type"]).replace("{{segment_timestamp}}", str(int(time)))
                f.write(f'#EXTINF:{segment_length}\n')
                f.write(f'{segment}\n')
    
            f.write("#EXT-X-ENDLIST\n")
    
    with open("master.m3u8", "w") as f:
        f.writelines(
            [
                '#EXTM3U\n',
                '#EXT-X-INDEPENDENT-SEGMENTS\n'
            ]
        )
    
        for profile in profiles:
            type_name = "audio" if "audio" in profile["mime_type"] else "video"
            codec_name = profile.get("audio_codec") or profile.get("video_codec")
            name = f"{type_name}_{profile["max_bitrate"]}_{codec_name}"
    
            if type_name == "video":
                f.write(
                    '#EXT-X-STREAM-INF:'
                    f'BANDWIDTH={profile["video_bitrate"]},'
                    f'CODECS="{profile["video_codec"]}",'
                    f'RESOLUTION={f'{profile["video_width"]}x{profile["video_height"]}'},'
                    'AUDIO="default-audio-group"\n'
                )
                f.write(f'{name}.m3u8\n')
            elif type_name == "audio":
                f.write(
                    '#EXT-X-MEDIA:'
                    'TYPE=AUDIO,'
                    f'URI="{name}.m3u8",'
                    'GROUP-ID="default-audio-group",'
                    f'NAME="{name}"\n'
                )
    on windows browser (for me at chrome) it isnt needed download through hls converted from json.

    Look at F12 Network, there you will find files which come from https://audio-ak.spotifycdn.com/audio. That are the encrypted file as m4a. Download them and decrypt them with the key.

    The kid;key you can get with your tool WVProxy2, but it must be a .wvd from a physical device not an emulated.

    thats the easiest method.
    Last edited by vitalka; 19th Jun 2025 at 04:05.
    Quote Quote  
  13. my code is for downloading videos, not single tracks
    Bypass HMACs, One-time-tokens and Lic.Wrapping: https://github.com/DevLARLEY/WidevineProxy2
    Quote Quote  
  14. Originally Posted by larley View Post
    my code is for downloading videos, not single tracks
    ahh danke dir!!! habe nicht näher darauf geschaut.
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!