@@ -152,7 +152,7 @@ private YoutubeParsingHelper() {
152152 * The client version for InnerTube requests with the {@code WEB} client, used as the last
153153 * fallback if the extraction of the real one failed.
154154 */
155- private static final String HARDCODED_CLIENT_VERSION = "2.20240410 .01.00" ;
155+ private static final String HARDCODED_CLIENT_VERSION = "2.20240718 .01.00" ;
156156
157157 /**
158158 * The hardcoded client version of the Android app used for InnerTube requests with this
@@ -163,7 +163,7 @@ private YoutubeParsingHelper() {
163163 * such as <a href="https://www.apkmirror.com/apk/google-inc/youtube/">APKMirror</a>.
164164 * </p>
165165 */
166- private static final String ANDROID_YOUTUBE_CLIENT_VERSION = "19.13.36 " ;
166+ private static final String ANDROID_YOUTUBE_CLIENT_VERSION = "19.28.35 " ;
167167
168168 /**
169169 * The hardcoded client version of the iOS app used for InnerTube requests with this client.
@@ -174,7 +174,7 @@ private YoutubeParsingHelper() {
174174 * Store page of the YouTube app</a>, in the {@code What’s New} section.
175175 * </p>
176176 */
177- private static final String IOS_YOUTUBE_CLIENT_VERSION = "19.14.3 " ;
177+ private static final String IOS_YOUTUBE_CLIENT_VERSION = "19.28.1 " ;
178178
179179 /**
180180 * The hardcoded client version used for InnerTube requests with the TV HTML5 embed client.
@@ -190,7 +190,7 @@ private YoutubeParsingHelper() {
190190 * The hardcoded client version used for InnerTube requests with the YouTube Music desktop
191191 * client.
192192 */
193- private static final String HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION = "1.20240403 .01.00" ;
193+ private static final String HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION = "1.20240715 .01.00" ;
194194
195195 private static String clientVersion ;
196196
@@ -219,31 +219,31 @@ private YoutubeParsingHelper() {
219219 * information.
220220 * </p>
221221 */
222- private static final String IOS_DEVICE_MODEL = "iPhone15,4 " ;
222+ private static final String IOS_DEVICE_MODEL = "iPhone16,2 " ;
223223
224224 /**
225- * Spoofing an iPhone 15 running iOS 17.4 .1 with the hardcoded version of the iOS app. To be
226- * used for the {@code "osVersion"} field in JSON POST requests.
225+ * Spoofing an iPhone 15 Pro Max running iOS 17.5 .1 with the hardcoded version of the iOS app.
226+ * To be used for the {@code "osVersion"} field in JSON POST requests.
227227 * <p>
228228 * The value of this field seems to use the following structure:
229229 * "iOS major version.minor version.patch version.build version", where
230230 * "patch version" is equal to 0 if it isn't set
231231 * The build version corresponding to the iOS version used can be found on
232- * <a href="https://theapplewiki.com/wiki/Firmware/iPhone/17.x#iPhone_15 ">
233- * https://theapplewiki.com/wiki/Firmware/iPhone/17.x#iPhone_15 </a>
232+ * <a href="https://theapplewiki.com/wiki/Firmware/iPhone/17.x#iPhone_15_Pro_Max ">
233+ * https://theapplewiki.com/wiki/Firmware/iPhone/17.x#iPhone_15_Pro_Max </a>
234234 * </p>
235235 *
236236 * @see #IOS_USER_AGENT_VERSION
237237 */
238- private static final String IOS_OS_VERSION = "17.4 .1.21E237 " ;
238+ private static final String IOS_OS_VERSION = "17.5 .1.21F90 " ;
239239
240240 /**
241- * Spoofing an iPhone 15 running iOS 17.4 .1 with the hardcoded version of the iOS app. To be
241+ * Spoofing an iPhone 15 running iOS 17.5 .1 with the hardcoded version of the iOS app. To be
242242 * used in the user agent for requests.
243243 *
244244 * @see #IOS_OS_VERSION
245245 */
246- private static final String IOS_USER_AGENT_VERSION = "17_4_1 " ;
246+ private static final String IOS_USER_AGENT_VERSION = "17_5_1 " ;
247247
248248 private static Random numberGenerator = new Random ();
249249
@@ -1301,31 +1301,49 @@ public static JsonBuilder<JsonObject> prepareTvHtml5EmbedJsonBuilder(
13011301 }
13021302
13031303 @ Nonnull
1304- public static byte [] createDesktopPlayerBody (
1304+ public static JsonObject getWebPlayerResponse (
1305+ @ Nonnull final Localization localization ,
1306+ @ Nonnull final ContentCountry contentCountry ,
1307+ @ Nonnull final String videoId ) throws IOException , ExtractionException {
1308+ final byte [] body = JsonWriter .string (
1309+ prepareDesktopJsonBuilder (localization , contentCountry )
1310+ .value (VIDEO_ID , videoId )
1311+ .value (CONTENT_CHECK_OK , true )
1312+ .value (RACY_CHECK_OK , true )
1313+ .done ())
1314+ .getBytes (StandardCharsets .UTF_8 );
1315+ final String url = YOUTUBEI_V1_URL + "player" + "?" + DISABLE_PRETTY_PRINT_PARAMETER
1316+ + "&$fields=microformat,playabilityStatus,storyboards,videoDetails" ;
1317+
1318+ return JsonUtils .toJsonObject (getValidJsonResponseBody (
1319+ getDownloader ().postWithContentTypeJson (
1320+ url , getYouTubeHeaders (), body , localization )));
1321+ }
1322+
1323+ @ Nonnull
1324+ public static byte [] createTvHtml5EmbedPlayerBody (
13051325 @ Nonnull final Localization localization ,
13061326 @ Nonnull final ContentCountry contentCountry ,
13071327 @ Nonnull final String videoId ,
13081328 @ Nonnull final Integer sts ,
1309- final boolean isTvHtml5DesktopJsonBuilder ,
1310- @ Nonnull final String contentPlaybackNonce ) throws IOException , ExtractionException {
1329+ @ Nonnull final String contentPlaybackNonce ) {
13111330 // @formatter:off
1312- return JsonWriter .string (( isTvHtml5DesktopJsonBuilder
1313- ? prepareTvHtml5EmbedJsonBuilder (localization , contentCountry , videoId )
1314- : prepareDesktopJsonBuilder ( localization , contentCountry ) )
1315- .object ("playbackContext " )
1316- . object ( "contentPlaybackContext" )
1317- // Signature timestamp from the JavaScript base player is needed to get
1318- // working obfuscated URLs
1319- .value ("signatureTimestamp " , sts )
1320- .value ( "referer" , "https://www.youtube.com/watch?v=" + videoId )
1331+ return JsonWriter .string (
1332+ prepareTvHtml5EmbedJsonBuilder (localization , contentCountry , videoId )
1333+ . object ( "playbackContext" )
1334+ .object ("contentPlaybackContext " )
1335+ // Signature timestamp from the JavaScript base player is needed to get
1336+ // working obfuscated URLs
1337+ . value ( "signatureTimestamp" , sts )
1338+ .value ("referer " , "https://www.youtube.com/watch?v=" + videoId )
1339+ .end ( )
13211340 .end ()
1322- .end ()
1323- .value (CPN , contentPlaybackNonce )
1324- .value (VIDEO_ID , videoId )
1325- .value (CONTENT_CHECK_OK , true )
1326- .value (RACY_CHECK_OK , true )
1327- .done ())
1328- .getBytes (StandardCharsets .UTF_8 );
1341+ .value (CPN , contentPlaybackNonce )
1342+ .value (VIDEO_ID , videoId )
1343+ .value (CONTENT_CHECK_OK , true )
1344+ .value (RACY_CHECK_OK , true )
1345+ .done ())
1346+ .getBytes (StandardCharsets .UTF_8 );
13291347 // @formatter:on
13301348 }
13311349
@@ -1366,7 +1384,7 @@ public static String getAndroidUserAgent(@Nullable final Localization localizati
13661384 */
13671385 @ Nonnull
13681386 public static String getIosUserAgent (@ Nullable final Localization localization ) {
1369- // Spoofing an iPhone 15 running iOS 17.4 .1 with the hardcoded version of the iOS app
1387+ // Spoofing an iPhone 15 running iOS 17.5 .1 with the hardcoded version of the iOS app
13701388 return "com.google.ios.youtube/" + IOS_YOUTUBE_CLIENT_VERSION
13711389 + "(" + IOS_DEVICE_MODEL + "; U; CPU iOS "
13721390 + IOS_USER_AGENT_VERSION + " like Mac OS X; "
0 commit comments