2121package org .schabi .newpipe .extractor .services .youtube ;
2222
2323import static org .schabi .newpipe .extractor .NewPipe .getDownloader ;
24+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .ANDROID_CLIENT_VERSION ;
25+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .DESKTOP_CLIENT_PLATFORM ;
26+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .IOS_CLIENT_VERSION ;
27+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .IOS_DEVICE_MODEL ;
28+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .IOS_USER_AGENT_VERSION ;
29+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .WEB_CLIENT_ID ;
30+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .WEB_CLIENT_NAME ;
31+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .WEB_HARDCODED_CLIENT_VERSION ;
32+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .WEB_REMIX_CLIENT_ID ;
33+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .WEB_REMIX_CLIENT_NAME ;
34+ import static org .schabi .newpipe .extractor .services .youtube .ClientsConstants .WEB_REMIX_HARDCODED_CLIENT_VERSION ;
2435import static org .schabi .newpipe .extractor .utils .Utils .HTTP ;
2536import static org .schabi .newpipe .extractor .utils .Utils .HTTPS ;
2637import static org .schabi .newpipe .extractor .utils .Utils .getStringResultFromRegexArray ;
@@ -144,55 +155,11 @@ private YoutubeParsingHelper() {
144155 */
145156 public static final String RACY_CHECK_OK = "racyCheckOk" ;
146157
147- /**
148- * The hardcoded client ID used for InnerTube requests with the {@code WEB} client.
149- */
150- private static final String WEB_CLIENT_ID = "1" ;
151-
152- /**
153- * The client version for InnerTube requests with the {@code WEB} client, used as the last
154- * fallback if the extraction of the real one failed.
155- */
156- private static final String HARDCODED_CLIENT_VERSION = "2.20240718.01.00" ;
157-
158- /**
159- * The hardcoded client version of the Android app used for InnerTube requests with this
160- * client.
161- *
162- * <p>
163- * It can be extracted by getting the latest release version of the app in an APK repository
164- * such as <a href="https://www.apkmirror.com/apk/google-inc/youtube/">APKMirror</a>.
165- * </p>
166- */
167- private static final String ANDROID_YOUTUBE_CLIENT_VERSION = "19.28.35" ;
168-
169- /**
170- * The hardcoded client version of the iOS app used for InnerTube requests with this client.
171- *
172- * <p>
173- * It can be extracted by getting the latest release version of the app on
174- * <a href="https://apps.apple.com/us/app/youtube-watch-listen-stream/id544007664/">the App
175- * Store page of the YouTube app</a>, in the {@code What’s New} section.
176- * </p>
177- */
178- private static final String IOS_YOUTUBE_CLIENT_VERSION = "20.03.02" ;
179-
180158 /**
181159 * The hardcoded client version used for InnerTube requests with the TV HTML5 embed client.
182160 */
183161 private static final String TVHTML5_SIMPLY_EMBED_CLIENT_VERSION = "2.0" ;
184162
185- /**
186- * The hardcoded client ID used for InnerTube requests with the YouTube Music desktop client.
187- */
188- private static final String YOUTUBE_MUSIC_CLIENT_ID = "67" ;
189-
190- /**
191- * The hardcoded client version used for InnerTube requests with the YouTube Music desktop
192- * client.
193- */
194- private static final String HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION = "1.20240715.01.00" ;
195-
196163 private static String clientVersion ;
197164
198165 private static String youtubeMusicClientVersion ;
@@ -212,41 +179,6 @@ private YoutubeParsingHelper() {
212179 private static final String CONTENT_PLAYBACK_NONCE_ALPHABET =
213180 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" ;
214181
215- /**
216- * The device machine id for the iPhone 15 Pro Max,
217- * used to get 60fps with the {@code iOS} client.
218- *
219- * <p>
220- * See <a href="https://gist.github.com/adamawolf/3048717">this GitHub Gist</a> for more
221- * information.
222- * </p>
223- */
224- private static final String IOS_DEVICE_MODEL = "iPhone16,2" ;
225-
226- /**
227- * Spoofing an iPhone 15 Pro Max running iOS 18.2.1 with the hardcoded version of the iOS app.
228- * To be used for the {@code "osVersion"} field in JSON POST requests.
229- * <p>
230- * The value of this field seems to use the following structure:
231- * "iOS major version.minor version.patch version.build version", where
232- * "patch version" is equal to 0 if it isn't set
233- * The build version corresponding to the iOS version used can be found on
234- * <a href="https://theapplewiki.com/wiki/Firmware/iPhone/18.x#iPhone_15_Pro_Max">
235- * https://theapplewiki.com/wiki/Firmware/iPhone/18.x#iPhone_15_Pro_Max</a>
236- * </p>
237- *
238- * @see #IOS_USER_AGENT_VERSION
239- */
240- private static final String IOS_OS_VERSION = "18.2.1.22C161" ;
241-
242- /**
243- * Spoofing an iPhone 15 Pro Max running iOS 18.2.1 with the hardcoded version of the iOS app.
244- * To be used in the user agent for requests.
245- *
246- * @see #IOS_OS_VERSION
247- */
248- private static final String IOS_USER_AGENT_VERSION = "18_2_1" ;
249-
250182 private static Random numberGenerator = new Random ();
251183
252184 private static final String FEED_BASE_CHANNEL_ID =
@@ -561,9 +493,9 @@ public static boolean isHardcodedClientVersionValid()
561493 .object ("client" )
562494 .value ("hl" , "en-GB" )
563495 .value ("gl" , "GB" )
564- .value ("clientName" , "WEB" )
565- .value ("clientVersion" , HARDCODED_CLIENT_VERSION )
566- .value ("platform" , "DESKTOP" )
496+ .value ("clientName" , WEB_CLIENT_NAME )
497+ .value ("clientVersion" , WEB_HARDCODED_CLIENT_VERSION )
498+ .value ("platform" , DESKTOP_CLIENT_PLATFORM )
567499 .value ("utcOffsetMinutes" , 0 )
568500 .end ()
569501 .object ("request" )
@@ -581,7 +513,7 @@ public static boolean isHardcodedClientVersionValid()
581513 .end ().done ().getBytes (StandardCharsets .UTF_8 );
582514 // @formatter:on
583515
584- final var headers = getClientHeaders (WEB_CLIENT_ID , HARDCODED_CLIENT_VERSION );
516+ final var headers = getClientHeaders (WEB_CLIENT_ID , WEB_HARDCODED_CLIENT_VERSION );
585517
586518 // This endpoint is fetched by the YouTube website to get the items of its main menu and is
587519 // pretty lightweight (around 30kB)
@@ -705,7 +637,7 @@ public static String getClientVersion() throws IOException, ExtractionException
705637
706638 // Fallback to the hardcoded one if it is valid
707639 if (isHardcodedClientVersionValid ()) {
708- clientVersion = HARDCODED_CLIENT_VERSION ;
640+ clientVersion = WEB_HARDCODED_CLIENT_VERSION ;
709641 return clientVersion ;
710642 }
711643
@@ -752,11 +684,11 @@ public static boolean isHardcodedYoutubeMusicClientVersionValid() throws IOExcep
752684 .object ()
753685 .object ("context" )
754686 .object ("client" )
755- .value ("clientName" , "WEB_REMIX" )
756- .value ("clientVersion" , HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION )
687+ .value ("clientName" , WEB_REMIX_CLIENT_NAME )
688+ .value ("clientVersion" , WEB_REMIX_HARDCODED_CLIENT_VERSION )
757689 .value ("hl" , "en-GB" )
758690 .value ("gl" , "GB" )
759- .value ("platform" , "DESKTOP" )
691+ .value ("platform" , DESKTOP_CLIENT_PLATFORM )
760692 .value ("utcOffsetMinutes" , 0 )
761693 .end ()
762694 .object ("request" )
@@ -775,8 +707,7 @@ public static boolean isHardcodedYoutubeMusicClientVersionValid() throws IOExcep
775707 // @formatter:on
776708
777709 final var headers = new HashMap <>(getOriginReferrerHeaders (YOUTUBE_MUSIC_URL ));
778- headers .putAll (getClientHeaders (YOUTUBE_MUSIC_CLIENT_ID ,
779- HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION ));
710+ headers .putAll (getClientHeaders (WEB_REMIX_CLIENT_ID , WEB_HARDCODED_CLIENT_VERSION ));
780711
781712 final Response response = getDownloader ().postWithContentTypeJson (url , headers , json );
782713 // Ensure to have a valid response
@@ -789,7 +720,7 @@ public static String getYoutubeMusicClientVersion()
789720 return youtubeMusicClientVersion ;
790721 }
791722 if (isHardcodedYoutubeMusicClientVersionValid ()) {
792- youtubeMusicClientVersion = HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION ;
723+ youtubeMusicClientVersion = WEB_REMIX_HARDCODED_CLIENT_VERSION ;
793724 return youtubeMusicClientVersion ;
794725 }
795726
@@ -1196,10 +1127,10 @@ public static JsonBuilder<JsonObject> prepareDesktopJsonBuilder(
11961127 .object ("client" )
11971128 .value ("hl" , localization .getLocalizationCode ())
11981129 .value ("gl" , contentCountry .getCountryCode ())
1199- .value ("clientName" , "WEB" )
1130+ .value ("clientName" , WEB_CLIENT_NAME )
12001131 .value ("clientVersion" , getClientVersion ())
12011132 .value ("originalUrl" , "https://www.youtube.com" )
1202- .value ("platform" , "DESKTOP" )
1133+ .value ("platform" , DESKTOP_CLIENT_PLATFORM )
12031134 .value ("utcOffsetMinutes" , 0 )
12041135 .value ("visitorData" , vData )
12051136 .end ()
@@ -1391,9 +1322,8 @@ public static byte[] createTvHtml5EmbedPlayerBody(
13911322 */
13921323 @ Nonnull
13931324 public static String getAndroidUserAgent (@ Nullable final Localization localization ) {
1394- // Spoofing an Android 14 device with the hardcoded version of the Android app
1395- return "com.google.android.youtube/" + ANDROID_YOUTUBE_CLIENT_VERSION
1396- + " (Linux; U; Android 14; "
1325+ return "com.google.android.youtube/" + ANDROID_CLIENT_VERSION
1326+ + " (Linux; U; Android 15; "
13971327 + (localization != null ? localization : Localization .DEFAULT ).getCountryCode ()
13981328 + ") gzip" ;
13991329 }
@@ -1413,11 +1343,8 @@ public static String getAndroidUserAgent(@Nullable final Localization localizati
14131343 */
14141344 @ Nonnull
14151345 public static String getIosUserAgent (@ Nullable final Localization localization ) {
1416- // Spoofing an iPhone 15 Pro Max running iOS 18.1.0
1417- // with the hardcoded version of the iOS app
1418- return "com.google.ios.youtube/" + IOS_YOUTUBE_CLIENT_VERSION
1419- + "(" + IOS_DEVICE_MODEL + "; U; CPU iOS "
1420- + IOS_USER_AGENT_VERSION + " like Mac OS X; "
1346+ return "com.google.ios.youtube/" + IOS_CLIENT_VERSION + "(" + IOS_DEVICE_MODEL
1347+ + "; U; CPU iOS " + IOS_USER_AGENT_VERSION + " like Mac OS X; "
14211348 + (localization != null ? localization : Localization .DEFAULT ).getCountryCode ()
14221349 + ")" ;
14231350 }
@@ -1428,8 +1355,7 @@ public static String getIosUserAgent(@Nullable final Localization localization)
14281355 @ Nonnull
14291356 public static Map <String , List <String >> getYoutubeMusicHeaders () {
14301357 final var headers = new HashMap <>(getOriginReferrerHeaders (YOUTUBE_MUSIC_URL ));
1431- headers .putAll (getClientHeaders (YOUTUBE_MUSIC_CLIENT_ID ,
1432- youtubeMusicClientVersion ));
1358+ headers .putAll (getClientHeaders (WEB_REMIX_CLIENT_ID , youtubeMusicClientVersion ));
14331359 return headers ;
14341360 }
14351361
0 commit comments