@@ -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.28.1 " ;
177+ private static final String IOS_YOUTUBE_CLIENT_VERSION = "19.45.4 " ;
178178
179179 /**
180180 * The hardcoded client version used for InnerTube requests with the TV HTML5 embed client.
@@ -235,15 +235,15 @@ private YoutubeParsingHelper() {
235235 *
236236 * @see #IOS_USER_AGENT_VERSION
237237 */
238- private static final String IOS_OS_VERSION = "17.5.1.21F90 " ;
238+ private static final String IOS_OS_VERSION = "18.1.0.22B83 " ;
239239
240240 /**
241241 * 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_5_1 " ;
246+ private static final String IOS_USER_AGENT_VERSION = "18_1_0 " ;
247247
248248 private static Random numberGenerator = new Random ();
249249
@@ -303,6 +303,23 @@ public static boolean isY2ubeURL(@Nonnull final URL url) {
303303 return url .getHost ().equalsIgnoreCase ("y2u.be" );
304304 }
305305
306+ public static String randomVisitorData (final ContentCountry country ) {
307+ final ProtoBuilder pbE2 = new ProtoBuilder ();
308+ pbE2 .string (2 , "" );
309+ pbE2 .varint (4 , numberGenerator .nextInt (1 , 256 ));
310+
311+ final ProtoBuilder pbE = new ProtoBuilder ();
312+ pbE .string (1 , country .getCountryCode ());
313+ pbE .bytes (2 , pbE2 .toBytes ());
314+
315+ final ProtoBuilder pb = new ProtoBuilder ();
316+ pb .string (1 , RandomStringFromAlphabetGenerator .generate (
317+ CONTENT_PLAYBACK_NONCE_ALPHABET , 11 , numberGenerator ));
318+ pb .varint (5 , System .currentTimeMillis () / 1000 - numberGenerator .nextInt (600000 ));
319+ pb .bytes (6 , pbE .toBytes ());
320+ return pb .toUrlencodedBase64 ();
321+ }
322+
306323 /**
307324 * Parses the duration string of the video expecting ":" or "." as separators
308325 *
@@ -1164,10 +1181,14 @@ public static JsonBuilder<JsonObject> prepareDesktopJsonBuilder(
11641181 public static JsonBuilder <JsonObject > prepareDesktopJsonBuilder (
11651182 @ Nonnull final Localization localization ,
11661183 @ Nonnull final ContentCountry contentCountry ,
1167- @ Nullable final String visitorData )
1184+ @ Nullable String visitorData )
11681185 throws IOException , ExtractionException {
1186+ if (visitorData == null ) {
1187+ visitorData = randomVisitorData (contentCountry );
1188+ }
1189+
11691190 // @formatter:off
1170- final JsonBuilder < JsonObject > builder = JsonObject .builder ()
1191+ return JsonObject .builder ()
11711192 .object ("context" )
11721193 .object ("client" )
11731194 .value ("hl" , localization .getLocalizationCode ())
@@ -1176,13 +1197,9 @@ public static JsonBuilder<JsonObject> prepareDesktopJsonBuilder(
11761197 .value ("clientVersion" , getClientVersion ())
11771198 .value ("originalUrl" , "https://www.youtube.com" )
11781199 .value ("platform" , "DESKTOP" )
1179- .value ("utcOffsetMinutes" , 0 );
1180-
1181- if (visitorData != null ) {
1182- builder .value ("visitorData" , visitorData );
1183- }
1184-
1185- return builder .end ()
1200+ .value ("utcOffsetMinutes" , 0 )
1201+ .value ("visitorData" , visitorData )
1202+ .end ()
11861203 .object ("request" )
11871204 .array ("internalExperimentFlags" )
11881205 .end ()
@@ -1256,6 +1273,7 @@ public static JsonBuilder<JsonObject> prepareIosMobileJsonBuilder(
12561273 .value ("platform" , "MOBILE" )
12571274 .value ("osName" , "iOS" )
12581275 .value ("osVersion" , IOS_OS_VERSION )
1276+ .value ("visitorData" , randomVisitorData (contentCountry ))
12591277 .value ("hl" , localization .getLocalizationCode ())
12601278 .value ("gl" , contentCountry .getCountryCode ())
12611279 .value ("utcOffsetMinutes" , 0 )
0 commit comments