lets find more clients
parent
603f6bbef1
commit
fb493cf1b0
67
analysis.py
67
analysis.py
|
@ -1,8 +1,6 @@
|
|||
import os
|
||||
import json
|
||||
|
||||
from numpy import array
|
||||
|
||||
def get_min_max_quality_label(formats):
|
||||
formats = [f for f in formats if f.get("qualityLabel") is not None]
|
||||
formats.sort(key=lambda x: x.get("width"))
|
||||
|
@ -40,10 +38,13 @@ def get_structure_tree(data, depth = 0):
|
|||
|
||||
|
||||
markdown = ""
|
||||
markdown += "|Client Name | Client Version | Quality Formats | Features/Attributes |\n"
|
||||
markdown += "|-------------|----------------|-----------------|----------|\n"
|
||||
markdown += "| ID/ClientName/Version | Quality Formats | Features/Limitations/Attributes |\n"
|
||||
markdown += "|---------------------------|-----------------|----------|\n"
|
||||
|
||||
txt_output = ""
|
||||
working_clients_output = ""
|
||||
working_versions_output = ""
|
||||
|
||||
video_id = ""
|
||||
|
||||
if not os.path.exists('results'):
|
||||
os.makedirs('results')
|
||||
|
@ -73,11 +74,22 @@ for client_id in client_ids:
|
|||
has_mpeg_dash = "dashManifest" in response_data_raw
|
||||
|
||||
try:
|
||||
client_name = response_data_raw.split('&c=')[1].split('&')[0]
|
||||
except Exception as ex:
|
||||
continue
|
||||
client_name = response_data_raw.split('%26c%3D')[1].split('%26')[0]
|
||||
except Exception:
|
||||
try:
|
||||
client_name = response_data_raw.split('&c=')[1].split('&')[0]
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
try:
|
||||
video_id = response_data_raw.split('&docid=')[1].split('&')[0]
|
||||
except Exception:
|
||||
print("missing doc id (video id)")
|
||||
|
||||
txt_output += client_name + ";" + client_version + "\n"
|
||||
working_clients_output += client_name + ";" + client_version + "\n"
|
||||
|
||||
if (client_version + "\n") not in working_versions_output:
|
||||
working_versions_output += client_version + "\n"
|
||||
|
||||
formats_combined = []
|
||||
|
||||
|
@ -111,16 +123,28 @@ for client_id in client_ids:
|
|||
formats_summary += get_unique_mime_str(formats_combined) + "<br><br>"
|
||||
|
||||
extraInfo = ""
|
||||
|
||||
if "music.youtube.com" in client_file:
|
||||
extraInfo += "• Music videos only<br>"
|
||||
|
||||
if "www.youtubekids.com" in client_file:
|
||||
extraInfo += "• \"For Kids\" content only<br>"
|
||||
|
||||
|
||||
if has_hls_format:
|
||||
extraInfo += "• HLS Support"
|
||||
extraInfo += "• HLS Support<br>"
|
||||
|
||||
if has_mpeg_dash:
|
||||
extraInfo += "• MPEG-DASH Support"
|
||||
extraInfo += "• MPEG-DASH Support<br>"
|
||||
|
||||
if client_name == "TVHTML5_SIMPLY_EMBEDDED_PLAYER":
|
||||
extraInfo += "• No Age-restrictions<br>"
|
||||
|
||||
|
||||
ignore_attributes = ["videoDetails", "playerConfig", "responseContext", "playabilityStatus", "streamingData", "playbackTracking", "trackingParams", "adPlacements", "playerAds", "adParams", "adBreakParams", "onResponseReceivedEndpoints", "playerSettingsMenuData"]
|
||||
|
||||
if extraInfo != "":
|
||||
extraInfo += "<br><br>"
|
||||
extraInfo += "<br>"
|
||||
|
||||
for attribute in response_data:
|
||||
if attribute not in ignore_attributes:
|
||||
|
@ -129,17 +153,28 @@ for client_id in client_ids:
|
|||
if extraInfo != "":
|
||||
extraInfo += "<br>"
|
||||
|
||||
extraInfo += "<details><summary>Response Structure</summary>" + get_structure_tree(response_data) +"</details>"
|
||||
extraInfo += "<details><summary>Show Response</summary>" + get_structure_tree(response_data) +"</details>"
|
||||
|
||||
|
||||
markdown += "|" + client_name + "<br>(" + str(client_id) + ")" + "|" + client_version + "|" + formats_summary + formatsStr + adaptiveFormatsStr + "|" + extraInfo + "|\n"
|
||||
markdown += "|ID: *" + str(client_id) + "*<br>" + client_name + "<br>" + client_version + "|" + formats_summary + formatsStr + adaptiveFormatsStr + "|" + extraInfo + "|\n"
|
||||
|
||||
break
|
||||
|
||||
readme_header = open("templates/readme_header.md", "r").read()
|
||||
readme_header = readme_header.replace("%videoId%", video_id)
|
||||
|
||||
f = open("results/working_clients.md", "w", encoding="utf-8")
|
||||
f.write(markdown)
|
||||
f.close()
|
||||
|
||||
f = open("results/working_clients.txt", "w")
|
||||
f.write(txt_output)
|
||||
f.close()
|
||||
f.write(working_clients_output)
|
||||
f.close()
|
||||
|
||||
f = open("results/working_unique_versions.txt", "w")
|
||||
f.write(working_versions_output)
|
||||
f.close()
|
||||
|
||||
f = open("readme.md", "w", encoding="utf-8")
|
||||
f.write(readme_header + markdown)
|
||||
f.close()
|
||||
|
|
|
@ -4,37 +4,70 @@ import os
|
|||
client_versions = open("payloads/client_versions.txt", "r").readlines()
|
||||
data_template = open("payloads/post_data.txt", "r").read()
|
||||
|
||||
headers = {
|
||||
"Origin": "https://www.youtube.com",
|
||||
"Referer": "https://www.youtube.com/",
|
||||
"Accept-Language": "de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.52"
|
||||
}
|
||||
innertube_hosts = [
|
||||
{
|
||||
"video_id": "vJz8QzO1VzQ", # normal video
|
||||
"domain": "www.youtube.com",
|
||||
"key": "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
|
||||
"headers": {
|
||||
"Origin": "https://www.youtube.com",
|
||||
"Referer": "https://www.youtube.com/",
|
||||
"Accept-Language": "de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.52"
|
||||
}
|
||||
},
|
||||
{
|
||||
"video_id": "pckuS--UlV4", # video "for kids"
|
||||
"domain": "www.youtubekids.com",
|
||||
"key": "AIzaSyBbZV_fZ3an51sF-mvs5w37OqqbsTOzwtU",
|
||||
"headers": {
|
||||
"Origin": "https://www.youtubekids.com",
|
||||
"Referer": "https://www.youtubekids.com/",
|
||||
"Accept-Language": "de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.52"
|
||||
}
|
||||
},
|
||||
{
|
||||
"video_id": "RY607kB2QiU", # music video
|
||||
"domain": "music.youtube.com",
|
||||
"key": "AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30",
|
||||
"headers": {
|
||||
"Origin": "https://music.youtube.com",
|
||||
"Referer": "https://music.youtube.com/",
|
||||
"Accept-Language": "de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.52"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
if not os.path.exists('responses'):
|
||||
os.makedirs('responses')
|
||||
|
||||
|
||||
for client_name_id in range(1, 100):
|
||||
for client_version in client_versions:
|
||||
client_version = client_version.replace("\n", "").replace("\r", "")
|
||||
if client_version == "":
|
||||
continue
|
||||
|
||||
try_id = str(client_name_id) + "_" + client_version
|
||||
for i, host in enumerate(innertube_hosts):
|
||||
|
||||
print("Try ClientId: " + str(client_name_id) + " ClientVersion: " + str(client_version))
|
||||
try_id = str(client_name_id) + "_" + client_version + "_" + str(len(innertube_hosts) - i) + "_" + host["domain"] + "_" + host["key"]
|
||||
|
||||
data = data_template.replace('%clientName%', str(client_name_id)).replace('%clientVersion%', client_version)
|
||||
print("Try ClientId: " + str(client_name_id) + " ClientVersion: " + str(client_version) + " @ " + host["domain"])
|
||||
|
||||
try:
|
||||
response = requests.post("https://www.youtube.com/youtubei/v1/player?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8", data=data, headers=headers, timeout=5)
|
||||
data = data_template.replace("%videoId%", host["video_id"]).replace('%clientName%', str(client_name_id)).replace('%clientVersion%', client_version)
|
||||
|
||||
print("Response Code: " + str(response.status_code))
|
||||
for i in range(0, 2):
|
||||
try:
|
||||
response = requests.post("https://" + host["domain"] + "/youtubei/v1/player?key=" + host["key"], data=data, headers=host["headers"], timeout=5)
|
||||
|
||||
if response.status_code == 200:
|
||||
out = open("responses/" + try_id + ".json", "w", encoding="utf-8")
|
||||
out.write(response.text)
|
||||
out.close()
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
print("Response Code: " + str(response.status_code))
|
||||
|
||||
if response.status_code == 200:
|
||||
out = open("responses/" + try_id + ".json", "w", encoding="utf-8")
|
||||
out.write(response.text)
|
||||
out.close()
|
||||
|
||||
break
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
|
|
|
@ -1,78 +1,3 @@
|
|||
2.20220325.00.00
|
||||
1.20150713
|
||||
1.20180713
|
||||
1.20200713
|
||||
1.20210713
|
||||
1.20220325
|
||||
2.20150719
|
||||
2.20180719
|
||||
2.20200719
|
||||
2.20210719
|
||||
2.20220325
|
||||
3.20220325
|
||||
4.20220325
|
||||
5.20220325
|
||||
6.20220325
|
||||
7.20220325
|
||||
8.20220325
|
||||
9.20220325
|
||||
10.20220325
|
||||
0.1
|
||||
0.2
|
||||
0.3
|
||||
0.4
|
||||
0.5
|
||||
0.6
|
||||
0.7
|
||||
0.8
|
||||
0.9
|
||||
1.0
|
||||
1.1
|
||||
1.2
|
||||
1.3
|
||||
1.4
|
||||
1.5
|
||||
1.6
|
||||
1.7
|
||||
1.8
|
||||
1.9
|
||||
2.0
|
||||
2.1.4
|
||||
2.13
|
||||
2.43
|
||||
3.0
|
||||
3.46
|
||||
3.26.1
|
||||
4.26.1
|
||||
5.26.1
|
||||
6.22.4
|
||||
7.0
|
||||
8.0
|
||||
9.0
|
||||
10.20
|
||||
11.20
|
||||
12.20
|
||||
13.20
|
||||
14.20
|
||||
15.20
|
||||
16.20
|
||||
18.24.100
|
||||
19.24.100
|
||||
20.24.100
|
||||
21.24.100
|
||||
22.24.100
|
||||
23.24.100
|
||||
24.24.100
|
||||
25.24.100
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
0
|
||||
0.0.1
|
||||
0.0.2
|
||||
|
@ -83,6 +8,118 @@
|
|||
0.0.7
|
||||
0.0.8
|
||||
0.0.9
|
||||
0.1
|
||||
0.2
|
||||
0.3
|
||||
0.4
|
||||
0.5
|
||||
0.6
|
||||
0.7
|
||||
0.8
|
||||
0.9
|
||||
1
|
||||
1.0
|
||||
1.0.0
|
||||
1.0.1
|
||||
1.1
|
||||
1.2
|
||||
1.20150713
|
||||
1.20180713
|
||||
1.20200713
|
||||
1.20210713
|
||||
1.20220325
|
||||
1.20220330
|
||||
1.3
|
||||
1.4
|
||||
1.5
|
||||
1.6
|
||||
1.7
|
||||
1.70.50
|
||||
1.8
|
||||
1.9
|
||||
10.20
|
||||
10.20220325
|
||||
11.20
|
||||
12.20
|
||||
13.20
|
||||
14.20
|
||||
15.11.34
|
||||
15.20
|
||||
16.20
|
||||
17.11.34
|
||||
18.11.34
|
||||
18.24.100
|
||||
19.11.100
|
||||
19.24.100
|
||||
2
|
||||
2.0
|
||||
2.1.4
|
||||
2.13
|
||||
2.20150719
|
||||
2.20180719
|
||||
2.20200719
|
||||
2.20210719
|
||||
2.20220325
|
||||
2.20220404
|
||||
2.43
|
||||
2.70.50
|
||||
20.24.100
|
||||
21.24.100
|
||||
22.01.100
|
||||
22.11.100
|
||||
22.24.100
|
||||
23.24.100
|
||||
24.24.100
|
||||
25.24.100
|
||||
3
|
||||
3.0
|
||||
3.10.3
|
||||
3.12.1
|
||||
3.20220325
|
||||
3.26.1
|
||||
3.46
|
||||
3.70.50
|
||||
3.8.1
|
||||
4
|
||||
4.00.50
|
||||
4.10.3
|
||||
4.10.50
|
||||
4.12.1
|
||||
4.20.50
|
||||
4.20220325
|
||||
4.26.1
|
||||
4.40.50
|
||||
4.70.00
|
||||
4.70.50
|
||||
5
|
||||
5.10.3
|
||||
5.12.1
|
||||
5.20220325
|
||||
5.26.1
|
||||
5.70.50
|
||||
6
|
||||
6.10.3
|
||||
6.12.1
|
||||
6.20220325
|
||||
6.22.4
|
||||
6.70.50
|
||||
6.8.1
|
||||
7
|
||||
7.0
|
||||
7.10.3
|
||||
7.20.3
|
||||
7.20220325
|
||||
7.30.3
|
||||
7.70.50
|
||||
8
|
||||
8.0
|
||||
8.10.3
|
||||
8.20220325
|
||||
8.70.50
|
||||
9
|
||||
9.0
|
||||
9.10.3
|
||||
9.20220325
|
||||
9.70.50
|
||||
9.8.1
|
||||
999999999
|
|
@ -1,41 +1,22 @@
|
|||
{
|
||||
"context": {
|
||||
"client": {
|
||||
"hl": "de",
|
||||
"gl": "DE",
|
||||
"hl": "en",
|
||||
"gl": "US",
|
||||
"clientName": %clientName%,
|
||||
"clientVersion": "%clientVersion%",
|
||||
"clientScreen": "WATCH",
|
||||
"mainAppWebInfo": {
|
||||
"graftUrl": "/watch?v=7t0SqerlBA0",
|
||||
"pwaInstallabilityStatus": "PWA_INSTALLABILITY_STATUS_CAN_BE_INSTALLED",
|
||||
"webDisplayMode": "WEB_DISPLAY_MODE_BROWSER",
|
||||
"isWebNativeShareAvailable": true
|
||||
},
|
||||
thirdParty: {
|
||||
embedUrl: 'https://www.youtube.com/',
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"lockedSafetyMode": false
|
||||
},
|
||||
"request": {
|
||||
"useSsl": true,
|
||||
"internalExperimentFlags": [],
|
||||
"consistencyTokenJars": []
|
||||
}
|
||||
},
|
||||
"videoId": "Zv11L-ZfrSg",
|
||||
"videoId": "%videoId%",
|
||||
"playbackContext": {
|
||||
"contentPlaybackContext": {
|
||||
"currentUrl": "/watch?v=7t0SqerlBA0",
|
||||
"vis": 0,
|
||||
"splay": false,
|
||||
"autoCaptionsDefaultOn": false,
|
||||
"autonavState": "STATE_ON",
|
||||
"html5Preference": "HTML5_PREF_WANTS",
|
||||
"signatureTimestamp": 19075,
|
||||
"referer": "https://www.youtube.com/results?search_query=test+age+restricted+video",
|
||||
"lactMilliseconds": "-1"
|
||||
}
|
||||
},
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,46 +1,56 @@
|
|||
WEB;2.20220325
|
||||
MWEB;2.20220325
|
||||
ANDROID;16.20
|
||||
IOS;16.20
|
||||
WEB;2.20220404
|
||||
MWEB;2.20220404
|
||||
ANDROID;17.11.34
|
||||
IOS;17.11.34
|
||||
TVHTML5;7.20220325
|
||||
TVLITE;2
|
||||
TVANDROID;1.0
|
||||
XBOXONEGUIDE;1.0
|
||||
ANDROID_CREATOR;21.24.100
|
||||
IOS_CREATOR;21.24.100
|
||||
ANDROID_CREATOR;22.11.100
|
||||
IOS_CREATOR;22.11.100
|
||||
TVAPPLE;1.0
|
||||
ANDROID_KIDS;7.10.3
|
||||
IOS_KIDS;7.10.3
|
||||
ANDROID_MUSIC;4.70.50
|
||||
ANDROID_TV;2.13
|
||||
IOS_MUSIC;4.70.50
|
||||
MWEB_TIER_2;9.20220325
|
||||
ANDROID_VR;0.1
|
||||
ANDROID_UNPLUGGED;5.26.1
|
||||
ANDROID_UNPLUGGED;6.12.1
|
||||
ANDROID_TESTSUITE;1.9
|
||||
WEB_MUSIC_ANALYTICS;0.2
|
||||
IOS_UNPLUGGED;5.26.1
|
||||
IOS_UNPLUGGED;6.12.1
|
||||
ANDROID_LITE;3.26.1
|
||||
IOS_EMBEDDED_PLAYER;2.0
|
||||
WEB_UNPLUGGED;1.20220325
|
||||
WEB_UNPLUGGED;1.20220330
|
||||
WEB_EXPERIMENTS;1
|
||||
TVHTML5_CAST;1.1
|
||||
ANDROID_EMBEDDED_PLAYER;16.20
|
||||
ANDROID_EMBEDDED_PLAYER;17.11.34
|
||||
WEB_EMBEDDED_PLAYER;9.20220325
|
||||
TV_UNPLUGGED_CAST;0.1
|
||||
TVHTML5_KIDS;3.20220325
|
||||
WEB_HEROES;0.1
|
||||
WEB_CREATOR;1.20220325
|
||||
WEB_MUSIC;1.0
|
||||
WEB_CREATOR;1.20220330
|
||||
TV_UNPLUGGED_ANDROID;0.1
|
||||
IOS_LIVE_CREATION_EXTENSION;16.20
|
||||
TVHTML5_UNPLUGGED;5.26.1
|
||||
IOS_MESSAGES_EXTENSION;16.20
|
||||
IOS_LIVE_CREATION_EXTENSION;17.11.34
|
||||
TVHTML5_UNPLUGGED;6.12.1
|
||||
IOS_MESSAGES_EXTENSION;17.11.34
|
||||
WEB_REMIX;1.20220330
|
||||
IOS_UPTIME;1.0
|
||||
WEB_UNPLUGGED_ONBOARDING;0.1
|
||||
WEB_UNPLUGGED_OPS;0.1
|
||||
WEB_UNPLUGGED_PUBLIC;0.1
|
||||
TVHTML5_VR;0.1
|
||||
ANDROID_TV_KIDS;1.0.0
|
||||
TVHTML5_SIMPLY;1.0
|
||||
WEB_KIDS;2.20220404
|
||||
MUSIC_INTEGRATIONS;0.1
|
||||
TVHTML5_YONGLE;0.1
|
||||
GOOGLE_ASSISTANT;0.1
|
||||
TVHTML5_SIMPLY_EMBEDDED_PLAYER;2.0
|
||||
WEB_INTERNAL_ANALYTICS;0.1
|
||||
WEB_PARENT_TOOLS;1.20220325
|
||||
WEB_PARENT_TOOLS;1.20220330
|
||||
GOOGLE_MEDIA_ACTIONS;0.1
|
||||
WEB_PHONE_VERIFICATION;1.0.0
|
||||
IOS_PRODUCER;0.1
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
2.20220404
|
||||
17.11.34
|
||||
7.20220325
|
||||
2
|
||||
1.0
|
||||
22.11.100
|
||||
7.10.3
|
||||
4.70.50
|
||||
2.13
|
||||
9.20220325
|
||||
0.1
|
||||
6.12.1
|
||||
1.9
|
||||
0.2
|
||||
3.26.1
|
||||
2.0
|
||||
1.20220330
|
||||
1.1
|
||||
3.20220325
|
||||
1.0.0
|
|
@ -0,0 +1,13 @@
|
|||
# YouTube-Internal-Clients
|
||||
|
||||
A script that discovers hidden internal clients of the YouTube (Innertube) API using bruteforce methods. The script tries `clientNames` with a sequential ID enumeration and crosses them with known `clientVersions`.
|
||||
The goal was to find a client that has no age restrictions implemented. With success.
|
||||
|
||||
## Contributors
|
||||
- [@MinePlayersPE](https://github.com/MinePlayersPE) - Mapped some version numbers in a [Gist](https://gist.github.com/MinePlayersPE/9875f2051c2dfdeb090543b8c6a9f7e6), which helped a lot
|
||||
- [@89z](https://github.com/89z) - Helped to find some missing clients
|
||||
|
||||
## Results
|
||||
|
||||
The script has found the following working clients tested on [this](https://www.youtube.com/watch?v=%videoId%) video:
|
||||
|
Loading…
Reference in New Issue