VideoHelp Forum
+ Reply to Thread
Results 1 to 4 of 4
Thread
  1. Member
    Join Date
    Aug 2023
    Location
    Turkey
    Search Comp PM
    i try to write one python code thad i can get header

    bud not get the same as in chrome

    any one know how to get the right header with python ?

    here my code ....

    Code:
    import requests
    
    url = "https://licanse.sever.com"
    
    response = requests.get(url)
    
    headers = response.headers
    
    with open("header.py", "w") as file:
        file.write("headers = {\n")
        for key, value in headers.items():
            file.write(f'    "{key}": "{value}",\n')
        file.write("}\n")
    
    print("Header to 'header.py' saved.")

    ps : the url its just example
    Quote Quote  
  2. Member
    Join Date
    Feb 2022
    Location
    Search the forum first!
    Search PM
    Code:
    import requests
    from rich.console import Console
    console = Console()
    url = "https://cwip-shaka-proxy.appspot.com/no_auth"
    
    response = requests.options(url)
    headers = response.headers
     # this will allow you to see what the response is and understand the data format.
    console.print(headers)
    
    # and you can contruct headers from this data
    # says call to the license server should be by POST
    # no Origin needed in fact this site doesn't need any request headers
    
    # to get the data to constuct your headers.py
    cont = headers['Content-Type']
    xcloud = headers['X-Cloud-Trace-Context']
     # etc
    # and put together to produce a reasonable headers file 
    # instead of printing you can save to a variable ready to write to file
    print( f"'Content-Type':'{cont}',\n'X-Cloud-Trace-Context':'{xcloud}',")   # just two items as example only
    Remember if you call the license server asking for headers all you will get is response headers - not request headers. So above we ask for options before-hand. The options response tell us what the request headers should contain. And you can make a good attempt at constructing headers well enough to pass scrutiny. In practice it is ail very much standard and you will only likely need to extract tokens or x-authority values by this method and add those to a standard file
    Last edited by A_n_g_e_l_a; 27th Sep 2023 at 06:27.
    Noob Starter Pack. Just download every Widevine mpd! Not kidding!.
    https://files.videohelp.com/u/301890/hellyes6.zip
    Quote Quote  
  3. Member
    Join Date
    Aug 2023
    Location
    Turkey
    Search Comp PM
    big thanks for you tips and example

    will try again

    bud realy not easy to understand bud will try my best
    if i succes i will share the file sure .. it will be very easy to get header and implent in the l3.py


    i will share what i begin and make samething bud not done with header section


    if you want you can chack this
    and mybe can anybudy help me to finish this

    you have 2 option
    1. use with mpd link get the pssh over kid and give the lisance url and
    (futher = creat correckt header from lisance server thad i wold found out how )
    and calculate you kid key

    2. all the same with manuel pssh .



    Code:
    import base64
    import requests
    import xml.etree.ElementTree as ET
    from pywidevine.L3.cdm import cdm, deviceconfig
    from base64 import b64encode
    from pywidevine.L3.getPSSH import get_pssh
    from pywidevine.L3.decrypt.wvdecryptcustom import WvDecrypt
    
    def get_pssh_from_url(url):
        response = requests.get(url)
        
        if response.status_code == 200:
            xml_data = response.text
            root = ET.fromstring(xml_data)
    
            namespace = {'xmlns': 'urn:mpeg:dash:schema:mpd:2011', 'cenc': 'urn:mpeg:cenc:2013'}
            kid_element = root.find(".//xmlns:ContentProtection[@cenc:default_KID]", namespaces=namespace)
    
            if kid_element is not None:
                kid_value = kid_element.get("{urn:mpeg:cenc:2013}default_KID")
                
                formatted_kid = '-'.join([kid_value[i:i+8] for i in range(0, len(kid_value), 8)])
                
                def get_pssh(keyId):
                    array_of_bytes = bytearray(b'\x00\x00\x002pssh\x00\x00\x00\x00')
                    array_of_bytes.extend(bytes.fromhex("edef8ba979d64acea3c827dcd51d21ed"))
                    array_of_bytes.extend(b'\x00\x00\x00\x12\x12\x10')
                    array_of_bytes.extend(bytes.fromhex(keyId.replace("-", "")))
                    return base64.b64encode(bytes.fromhex(array_of_bytes.hex()))
                
                pssh = get_pssh(kid_value)
                
                print(f"KID: {formatted_kid}\n")
                print(f"PSSH: {pssh.decode('utf-8')}")
                
                return pssh
            else:
                print("KID bulunamadı.")
        else:
            print(f"URL'ye erişilemedi. Hata kodu: {response.status_code}")
        return None
    
    def write_headers_to_file(response):
        headers = response.headers
        with open("header.py", "w") as file:
            file.write("headers = {\n")
            for key, value in headers.items():
                file.write(f'    "{key}": "{value}",\n')
            file.write("}\n")
        print("Header bilgileri 'header.py' dosyasına kaydedildi.")
    
    def get_license_url():
        url = input('License URL: ')
        
        response = requests.get(url)
        write_headers_to_file(response)
    
        return url
    
    def perform_decryption(pssh, lic_url):
        wvdecrypt = WvDecrypt(init_data_b64=pssh, cert_data_b64=b'', device=deviceconfig.device_android_generic)
        widevine_license = requests.post(url=lic_url, data=wvdecrypt.get_challenge())
    
        if not widevine_license.ok:
            print("License isteği başarısız: \n", widevine_license.content)
            return False, []
    
        license_b64 = b64encode(widevine_license.content)
        wvdecrypt.update_license(license_b64)
        Correct, keys = wvdecrypt.start_process()
    
        if Correct:
            with open("output.txt", "a") as output_file:
                output_file.write('\n')
                output_file.write(f"PSSH: {pssh}\n")
                output_file.write("License URL: " + lic_url + '\n')
                for key in keys:
                    output_file.write('--key ' + key + '\n')
            print("Çıktı başarıyla 'output.txt' dosyasına eklenmiştir.")
            return True, keys
        else:
            print("Decrypt işlemi başarısız.")
            return False, []
    
    
    def get_manual_pssh():
        pssh = input('Manual PSSH Input: ')
        return pssh
    
    
        license_b64 = b64encode(widevine_license.content)
        wvdecrypt.update_license(license_b64)
        Correct, keys = wvdecrypt.start_process()
    
        if Correct:
            with open("output.txt", "a") as output_file:
                output_file.write('\n')
                output_file.write(f"PSSH: {pssh}\n")
                output_file.write("License URL: " + lic_url + '\n')
                for key in keys:
                    output_file.write('--key ' + key + '\n')
            print("Çıktı başarıyla 'output.txt' dosyasına eklenmiştir.")
            return True, keys
        else:
            print("Decrypt işlemi başarısız.")
            return False, []
    
    while True:
        choice = input("Press For MPD URL: (1)   Manual PSSH Input: (2)   Exit: (0): ")
    
        if choice == '0':
            break
        elif choice != '1' and choice != '2':
            print("Geçersiz seçenek.")
            continue
    
        if choice == '1':
            mpd_url = input("MPD URL: ")
            pssh = get_pssh_from_url(mpd_url)
        elif choice == '2':
            pssh = get_manual_pssh()  # Prompt for manual PSSH input
    
        if pssh is None:
            print("PSSH alınamadı.")
            continue
    
        lic_url = get_license_url()
        success, keys = perform_decryption(pssh, lic_url)
    
        if success:
            print("Decrypt işlemi başarılı.")
            for key in keys:
                print("--key", key)
        else:
            print("Decrypt işlemi başarısız.")
    Last edited by senkron24; 27th Sep 2023 at 11:13.
    Quote Quote  
  4. Member
    Join Date
    Aug 2023
    Location
    Turkey
    Search Comp PM
    Originally Posted by A_n_g_e_l_a View Post
    Code:
    import requests
    from rich.console import Console
    console = Console()
    url = "https://cwip-shaka-proxy.appspot.com/no_auth"
    
    response = requests.options(url)
    headers = response.headers
     # this will allow you to see what the response is and understand the data format.
    console.print(headers)
    
    # and you can contruct headers from this data
    # says call to the license server should be by POST
    # no Origin needed in fact this site doesn't need any request headers
    
    # to get the data to constuct your headers.py
    cont = headers['Content-Type']
    xcloud = headers['X-Cloud-Trace-Context']
     # etc
    # and put together to produce a reasonable headers file 
    # instead of printing you can save to a variable ready to write to file
    print( f"'Content-Type':'{cont}',\n'X-Cloud-Trace-Context':'{xcloud}',")   # just two items as example only
    Remember if you call the license server asking for headers all you will get is response headers - not request headers. So above we ask for options before-hand. The options response tell us what the request headers should contain. And you can make a good attempt at constructing headers well enough to pass scrutiny. In practice it is ail very much standard and you will only likely need to extract tokens or x-authority values by this method and add those to a standard file


    I had time to examine more, but there is such a situation.

    example
    The data we receive from Chrome and the data we receive from here do not match and it seems to bring wrong information, for example.

    chrome

    Code:
    headers = {
        'authority': 'prod.spark.ziggogo.tv',
        'accept': '*/*',
        'accept-language': 'tr-TR,tr;q=0.9',
        # 'cookie': 'OptanonAlertBoxClosed=2023-09-26T16:41:27.075Z; rxVisitor=16957464766279HHLCUB8N0KGPKPEAFUJUN4P25N4SKEF; dtCookie=v_4_srv_35_sn_C36448F1C917DD4634525D8A1249F3F5_app-3A9bed77b55cacea1c_1_ol_0_perc_100000_mul_1; dtSa=-; OptanonConsent=isGpcEnabled=0&datestamp=Tue+Sep+26+2023+21%3A39%3A38+GMT%2B0300+(GMT%2B03%3A00)&version=202306.2.0&browserGpcFlag=0&isIABGlobal=false&hosts=&consentId=a16bbc10-04dc-48f9-b7df-979cb2423feb&interactionCount=1&landingPath=NotLandingPage&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1&geolocation=%3B&AwaitingReconsent=false; ACCESSTOKEN=eyJ0eXAiOiJKV1QiLCJraWQiOiJvZXNwX3Rva2VuX3Byb2RfMjAyMDA4MTkiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ3ZWItYXBpLXByb2Qtb2JvLmhvcml6b24udHYiLCJzaWQiOiI2M2RkMWRlZWRjOGVjZGUyOTc2YzM3OGEzNTZjMjczMzYzNjg2NzA4YjI5MGJmMDQ4NWYwMzBiYTc5NGFhMjk3IiwiaWF0IjoxNjk1NzUzNTc4LCJleHAiOjE2OTU3NjA3NzgsInN1YiI6IjE4NjQyOTc0X25sIn0.Gx7vJxXE5yYlTAKVgncyd4r6wlrgZfKrX_YPgOeUjz8; CLAIMSTOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkZXZpY2VzIjpbXSwiY3VzdG9tZXJJZCI6IjE4NjQyOTc0X25sIiwicHJvZmlsZXMiOlsiMDA2MGU1YjUtMzM2My00NzFjLWE4MWMtODE5YTgzYWI5OGE5Il0sImV4cCI6MTY5NTgzOTk3OH0.uARL9tPG4c1IEdZXI5h6fCEMqJp7-4g8jeStSbsDFdM; rxvt=1695755396912|1695753577156; dtPC=35$153577154_920h-vCMPIQUUJREAIRUGDTOHLRKRWEUBRUGCL-0e0',
        'devicename': 'Google%20Chrome',
        'origin': 'https://www.ziggogo.tv',
        'referer': 'https://www.ziggogo.tv/',
        'sec-ch-ua': '"Google Chrome";v="117", "Not;A=Brand";v="8", "Chromium";v="117"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-site',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
        'x-cus': '18642974_nl',
        'x-drm-schemeid': 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed',
        'x-go-dev': '0e6a7a87-aa06-4ee7-9bb6-9c53dccf8305',
        'x-oesp-username': 'kontak4@hotmail.com',
        'x-profile': '0060e5b5-3363-471c-a81c-819a83ab98a9',
        'x-streaming-token': 'YXNzVHlwPU9yaW9uLURBU0gmYy1pcC11bmxvY2tlZD0xJmNvbklkPU5MXzAwMDAxMV8wMTk1NjMmY29uVHlwZT00JmN1c0lkPTE4NjQyOTc0X25sJmRldkZhbT13ZWItZGVza3RvcCZkcj0wJmRybUNvbklkPW5sX3R2X3N0YW5kYWFyZF9jZW5jJmV4cGlyeT0xNjk1NzUzNzQ2JmZuPXNoYTI1NiZwYXRoVVJJPSUyRmRhc2glMkZOTF8wMDAwMTFfMDE5NTYzJTJGJTJBJnByb2ZpbGU9MDA2MGU1YjUtMzM2My00NzFjLWE4MWMtODE5YTgzYWI5OGE5JnJldXNlPS0xJnNMaW09MyZzZXNJZD1oUGVnMzZqWW5iTVFWdzZKbHc0ZHVBTWVLVUhEUkY0ZjRjb2Umc2VzVGltZT0xNjk1NzUzNTk2JnN0ckxpbT0zLGU2MGU3N2M3YjhkZThiNzg0NjU1OWQyYjBhNGMwNDE0ODJiY2FkMzEwZDUxYWU0OThiODNlNDI3YjBkYWIwNjA=',
        'x-tracking-id': '5242f1b071c6b4c053ee8cb4a0c36a9aad8dc3e121c905e3b69ccb634464ca66',
        'content-type': 'application/x-www-form-urlencoded',
    }
    python code get header


    Code:
    headers = {
        "Content-Type": "application/json",
        "Content-Length": "141",
        "Server-Timing": "dtRpid;desc="-1964344660", dtSInfo;desc="0"",
        "X-OneAgent-JS-Injection": "true",
        "x-request-id": "cd41f6f63c052c8e04c3bac480b2ab2b",
        "X-Content-Type-Options": "nosniff",
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Methods": "GET, POST, PUT, OPTIONS, DELETE, HEAD, PATCH",
        "Access-Control-Allow-Headers": "Accept-Charset, Accept-Encoding, Access-Control-Request-Headers, Access-Control-Request-Method, Authorization, Cache-Control, Connection, Content-Encoding, Content-Type, Content-Length, Cookie, DNT, Date, Host, If-Modified-Since, Keep-Alive, Origin, Referer, Server, TokenIssueTime, Transfer-Encoding, User-Agent, Vary, X-CustomHeader, X-Requested-With, password, username, x-request-id, x-ratelimit-app, x-guest-token, X-HTTP-Method-Override, x-oesp-username, x-oesp-token, x-cus, x-dev, X-Client-Id, X-Device-Code, X-Language-Code, UserRole, x-session-id, x-entitlements-token, x-go-dev, x-profile, x-api-key, nv-authorizations, X-Viewer-Id, x-oesp-profile-id, x-streaming-token, x-streaming-token-refresh-interval, x-drm-device-id, x-profile-id, x-ui-language, deviceName, x-drm-schemeId, x-refresh-token, X-Username, Location, x-tracking-id",
        "Access-Control-Expose-Headers": "x-streaming-token, x-streaming-token-refresh-interval, x-drm-device-id, x-profile-id, x-ui-language, deviceName, x-drm-schemeId, nv-qm-signature, nv-qm-version, x-refresh-token, Location",
        "Access-Control-Max-Age": "1728000",
        "X-EdgeConnect-MidMile-RTT": "5",
        "X-EdgeConnect-Origin-MEX-Latency": "11",
        "Date": "Tue, 26 Sep 2023 18:50:52 GMT",
        "Connection": "keep-alive",
        "Set-Cookie": "dtCookie=v_4_srv_31_sn_E41B342C05FBCE6AFADCA0ADB50C3D33_perc_100000_ol_0_mul_1_app-3Aea7c4b59f27d43eb_1; Path=/; Domain=.horizon.tv",
        "Access-Control-Allow-Origin": "https://www.horizon.tv",
    }
    Quote Quote  



Similar Threads

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