Hi everyone,
I'm working on a Python script to retrieve Widevine keys from a VdoCipher stream. The script seems to work well up to a certain point: it successfully parses the player URL, finds the MPD and the PSSH.
However, when I send the POST request to the license server (https://license.vdocipher.com/auth), I consistently get a 403 Forbidden error with the message: {"code":2048,"message":"Authentication failed"}.
I've tried to structure the final JSON payload and headers to mimic what a browser would send, but I must be missing something. I've confirmed that the player URL I'm using as input is active and works correctly when opened in a browser.
Any help in figuring out what's wrong with my license request would be greatly appreciated.
I'm using a real WVD, extracted from a device.
Code:https://player.vdocipher.com/v2/?otp=20160313versUSE32305v64nCQtNBmVl8bAvs0U57QsEOH1IkKIADm3TfM6vJ5FT&playbackInfo=eyJ2aWRlb0lkIjoiMGQ4YzczYmYzODBhNDE5NWEyYTZiMjk3ZWZjNzhjNjEifQ%3D%3D&player=r36ybRfkhOyoRUZa&primaryColor=7a2940
Code:# Arquivo: from pywidevine.py (VERSÃO FINAL COM PAYLOAD CORRETO) from pywidevine.device import Device from pywidevine.pssh import PSSH from pywidevine.cdm import Cdm from bs4 import BeautifulSoup from urllib.parse import urlparse, parse_qs import requests import base64 import json import re import sys # Lembre-se de manter o caminho com a barra inicial wv_CDM = "/content/samsung_sm-a556e_18.0.0@342415000_2305dd0b_34137_l3.wvd" input_url = input('Cole a URL COMPLETA do player (a que funciona no navegador): ') # Strip leading/trailing whitespace from the input URL input_url = input_url.strip() # Replace & with & in the input URL input_url = input_url.replace('&', '&') try: parsed_url = urlparse(input_url) query_params = parse_qs(parsed_url.query) otp = query_params.get('otp', [None])[0] playback_info = query_params.get('playbackInfo', [None])[0] if not otp or not playback_info: raise ValueError("A URL não contém 'otp' ou 'playbackInfo'") except Exception as e: print(f"\n[ERRO FATAL] A URL fornecida é inválida ou está incompleta: {e}") sys.exit() # Add print statements to inspect otp and playback_info print(f"\n[DEBUG] Extracted OTP: {otp}") print(f"[DEBUG] Extracted PlaybackInfo: {playback_info}") iframe_url = input_url headers_player = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Accept-Language': 'pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3', 'Connection': 'keep-alive', 'Host': 'player.vdocipher.com', 'Referer': iframe_url, 'Sec-Fetch-Dest': 'iframe', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'cross-site', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0', } print(f"\n[INFO] Buscando player: {iframe_url}") try: response = requests.get(iframe_url, headers=headers_player) response.raise_for_status() iframe = response.content.decode() except requests.exceptions.RequestException as e: print(f"\n[ERRO DE REDE] Falha ao acessar a URL do player: {e}") sys.exit() soup = BeautifulSoup(iframe, 'html.parser') script_tag = soup.find('script', {'type': 'application/json'}) if script_tag is None: print("\n[ERRO FATAL] Não foi possível encontrar os metadados do vídeo.") print("Causa Probável: A URL/OTP expirou. Tente com uma nova URL.") sys.exit() mpd_path = json.loads(script_tag.string) mpd_link = mpd_path['dash']['manifest'] try: get_pssh = re.search('<cenc:pssh>(.*)</cenc:pssh>', requests.get(mpd_link).text).group(1) except (AttributeError, requests.exceptions.RequestException): print(f"\n[ERRO FATAL] Não foi possível encontrar o PSSH no MPD: {mpd_link}") sys.exit() print('\n--- INFORMAÇÕES ENCONTRADAS ---') print('PSSH:', get_pssh) print(f'MPD: {mpd_link}\n') # --- DADOS PARA O PEDIDO DE LICENÇA CORRIGIDOS --- # Adicionamos 'href' e 'tech' para uma autorização válida json_data = { "otp": otp, "playbackInfo": playback_info, "href": input_url, "tech": "wv" } # --- FIM DA CORREÇÃO --- pssh = PSSH(get_pssh) device = Device.load(wv_CDM) cdm = Cdm.from_device(device) session_id = cdm.open() challenge = cdm.get_license_challenge(session_id, pssh) json_data["licenseRequest"] = base64.b64encode(challenge).decode("utf-8") # Encode the entire json_data object and put it under the 'token' key - Reverting to this structure based on the "request unwrapping failed" error and re-examining the likely correct structure token_payload = {"token": base64.b64encode(json.dumps(json_data).encode("utf-8")).decode("utf-8")} headers_license = { 'Accept': '*/*', 'Accept-Language': 'pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3', 'content-type': 'application/json', 'Host': 'license.vdocipher.com', 'Origin': 'https://player.vdocipher.com', 'Referer': iframe_url, 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-site', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/100101 Firefox/100.0', # Corrected User-Agent typo 'vdo-sdk': 'VdoWeb/2.5.2' } print("[INFO] Solicitando licença...") # Sending json_data directly as the request body response = requests.post("https://license.vdocipher.com/auth", headers=headers_license, json=token_payload) if not response.ok: print(f'ERRO: {response}\n{response.text}') cdm.close(session_id) sys.exit() print("\n[SUCCESS] Licença recebida! Obtendo chaves...") license = base64.b64decode(response.json()["license"]) cdm.parse_license(session_id, license) for key in cdm.get_keys(session_id): if key.type != 'SIGNING': print(f"✅ [KEY]: {key.kid.hex}:{key.key.hex()}") cdm.close(session_id)
Support our site by donate $5 directly to us Thanks!!!
Try StreamFab Downloader and download streaming video from Netflix, Amazon!
Try StreamFab Downloader and download streaming video from Netflix, Amazon!
+ Reply to Thread
Results 1 to 2 of 2
-
-
Recently, VdoCipher started showing error 2074 (Please open in Android app) to license requests from Android CDMs, even in real browsers with OpenWV or Vineless. Probably makes no sense without something to do about integrity tokens.
Similar Threads
-
How to get the widevine pssh from init mp4 JUST using python script?
By ancientbanana in forum Video Streaming DownloadingReplies: 14Last Post: 20th Nov 2024, 11:57 -
Vdocipher decoding tool
By TatsP in forum Video Streaming DownloadingReplies: 5Last Post: 11th May 2024, 14:28 -
script widevine
By teosaurus45 in forum Video Streaming DownloadingReplies: 14Last Post: 26th Sep 2023, 06:14 -
Found an awesome script to download widevine content (mpd) and decrypt it
By royjeon215 in forum Latest Video NewsReplies: 8Last Post: 11th Nov 2021, 15:26 -
Decoding manifest.mpd (Widevine)
By WaitForIt in forum Video Streaming DownloadingReplies: 6Last Post: 7th Jun 2021, 13:44