Skip to content

Commit 1dad3bf

Browse files
committed
[YouTube] Update again hardcoded client versions and update mobile user agents
Also provide ability to get mobile user-agents used for mobile InnerTube requests and deduplicate related code.
1 parent 3d38459 commit 1dad3bf

1 file changed

Lines changed: 60 additions & 25 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,18 @@ private YoutubeParsingHelper() {
9494
public static final String CPN = "cpn";
9595
public static final String VIDEO_ID = "videoId";
9696

97-
private static final String HARDCODED_CLIENT_VERSION = "2.20220114.01.00";
97+
private static final String HARDCODED_CLIENT_VERSION = "2.20220315.01.00";
9898
private static final String HARDCODED_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
9999

100100
private static final String ANDROID_YOUTUBE_KEY = "AIzaSyA8eiZmM1FaDVjRy-df2KTyQ_vz_yYM39w";
101101
private static final String IOS_YOUTUBE_KEY = "AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc";
102-
private static final String MOBILE_YOUTUBE_CLIENT_VERSION = "16.49.38";
102+
private static final String MOBILE_YOUTUBE_CLIENT_VERSION = "17.10.35";
103103

104104
private static String clientVersion;
105105
private static String key;
106106

107107
private static final String[] HARDCODED_YOUTUBE_MUSIC_KEY =
108-
{"AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30", "67", "1.20220110.00.00"};
108+
{"AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30", "67", "1.20220309.01.00"};
109109
private static String[] youtubeMusicKey;
110110

111111
private static boolean keyAndVersionExtracted = false;
@@ -973,44 +973,37 @@ public static JsonObject getJsonAndroidPostResponse(
973973
final byte[] body,
974974
@Nonnull final Localization localization,
975975
@Nullable final String endPartOfUrlRequest) throws IOException, ExtractionException {
976-
final Map<String, List<String>> headers = new HashMap<>();
977-
headers.put("Content-Type", Collections.singletonList("application/json"));
978-
// Spoofing an Android 11 device with the hardcoded version of the Android app
979-
headers.put("User-Agent", Collections.singletonList("com.google.android.youtube/"
980-
+ MOBILE_YOUTUBE_CLIENT_VERSION + " (Linux; U; Android 11; "
981-
+ localization.getCountryCode() + ") gzip"));
982-
headers.put("X-Goog-Api-Format-Version", Collections.singletonList("2"));
983-
984-
final String baseEndpointUrl = "https://youtubei.googleapis.com/youtubei/v1/" + endpoint
985-
+ "?key=" + ANDROID_YOUTUBE_KEY + DISABLE_PRETTY_PRINT_PARAMETER;
986-
987-
final Response response = getDownloader().post(isNullOrEmpty(endPartOfUrlRequest)
988-
? baseEndpointUrl : baseEndpointUrl + endPartOfUrlRequest,
989-
headers, body, localization);
990-
991-
return JsonUtils.toJsonObject(getValidJsonResponseBody(response));
976+
return getMobilePostResponse(endpoint, body, localization,
977+
getAndroidUserAgent(localization), ANDROID_YOUTUBE_KEY, endPartOfUrlRequest);
992978
}
993979

994980
public static JsonObject getJsonIosPostResponse(
995981
final String endpoint,
996982
final byte[] body,
997983
@Nonnull final Localization localization,
998984
@Nullable final String endPartOfUrlRequest) throws IOException, ExtractionException {
985+
return getMobilePostResponse(endpoint, body, localization, getIosUserAgent(localization),
986+
IOS_YOUTUBE_KEY, endPartOfUrlRequest);
987+
}
988+
989+
private static JsonObject getMobilePostResponse(
990+
final String endpoint,
991+
final byte[] body,
992+
@Nonnull final Localization localization,
993+
@Nonnull final String userAgent,
994+
@Nonnull final String key,
995+
@Nullable final String endPartOfUrlRequest) throws IOException, ExtractionException {
999996
final Map<String, List<String>> headers = new HashMap<>();
1000997
headers.put("Content-Type", Collections.singletonList("application/json"));
1001-
// Spoofing an iPhone 13 running iOS 15.2 with the hardcoded mobile client version
1002-
headers.put("User-Agent", Collections.singletonList("com.google.ios.youtube/"
1003-
+ MOBILE_YOUTUBE_CLIENT_VERSION + "(iPhone14,5; U; CPU iOS 15_2 like Mac OS X; "
1004-
+ localization.getCountryCode() + ")"));
998+
headers.put("User-Agent", Collections.singletonList(userAgent));
1005999
headers.put("X-Goog-Api-Format-Version", Collections.singletonList("2"));
10061000

10071001
final String baseEndpointUrl = "https://youtubei.googleapis.com/youtubei/v1/" + endpoint
1008-
+ "?key=" + IOS_YOUTUBE_KEY + DISABLE_PRETTY_PRINT_PARAMETER;
1002+
+ "?key=" + key + DISABLE_PRETTY_PRINT_PARAMETER;
10091003

10101004
final Response response = getDownloader().post(isNullOrEmpty(endPartOfUrlRequest)
10111005
? baseEndpointUrl : baseEndpointUrl + endPartOfUrlRequest,
10121006
headers, body, localization);
1013-
10141007
return JsonUtils.toJsonObject(getValidJsonResponseBody(response));
10151008
}
10161009

@@ -1233,6 +1226,48 @@ public static byte[] createDesktopPlayerBody(
12331226
// @formatter:on
12341227
}
12351228

1229+
/**
1230+
* Get the user-agent string used as the user-agent for InnerTube requests with the Android
1231+
* client.
1232+
*
1233+
* If the {@link Localization} provided is {@code null}, fallbacks to
1234+
* {@link Localization#DEFAULT the default one}.
1235+
*
1236+
* @param localization the {@link Localization} to set in the user-agent
1237+
* @return the Android user-agent used for InnerTube requests with the Android client,
1238+
* depending on the {@link Localization} provided
1239+
*/
1240+
@Nonnull
1241+
public static String getAndroidUserAgent(@Nullable final Localization localization) {
1242+
// Spoofing an Android 12 device with the hardcoded version of the Android app
1243+
return "com.google.android.youtube/" + MOBILE_YOUTUBE_CLIENT_VERSION
1244+
+ " (Linux; U; Android 12; "
1245+
+ (localization != null ? localization.getCountryCode()
1246+
: Localization.DEFAULT.getCountryCode())
1247+
+ ") gzip";
1248+
}
1249+
1250+
/**
1251+
* Get the user-agent string used as the user-agent for InnerTube requests with the iOS
1252+
* client.
1253+
*
1254+
* If the {@link Localization} provided is {@code null}, fallbacks to
1255+
* {@link Localization#DEFAULT the default one}.
1256+
*
1257+
* @param localization the {@link Localization} to set in the user-agent
1258+
* @return the iOS user-agent used for InnerTube requests with the iOS client, depending on the
1259+
* {@link Localization} provided
1260+
*/
1261+
@Nonnull
1262+
public static String getIosUserAgent(@Nullable final Localization localization) {
1263+
// Spoofing an iPhone 13 running iOS 15.4 with the hardcoded mobile client version
1264+
return "com.google.ios.youtube/" + MOBILE_YOUTUBE_CLIENT_VERSION
1265+
+ "(iPhone14,5; U; CPU iOS 15_4 like Mac OS X; "
1266+
+ (localization != null ? localization.getCountryCode()
1267+
: Localization.DEFAULT.getCountryCode())
1268+
+ ")";
1269+
}
1270+
12361271
/**
12371272
* Add required headers and cookies to an existing headers Map.
12381273
* @see #addClientInfoHeaders(Map)

0 commit comments

Comments
 (0)