Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,19 @@ private ClientsConstants() {
* The client version for InnerTube requests with the {@code WEB} client, used as the last
* fallback if the extraction of the real one failed.
*/
static final String WEB_HARDCODED_CLIENT_VERSION = "2.20250122.04.00";
static final String WEB_HARDCODED_CLIENT_VERSION = "2.20260120.01.00";

// WEB_REMIX (YouTube Music) client fields

static final String WEB_REMIX_CLIENT_ID = "67";
static final String WEB_REMIX_CLIENT_NAME = "WEB_REMIX";
static final String WEB_REMIX_HARDCODED_CLIENT_VERSION = "1.20250122.01.00";

// TVHTML5 (YouTube on TVs and consoles using HTML5) client fields
static final String TVHTML5_CLIENT_ID = "7";
static final String TVHTML5_CLIENT_NAME = "TVHTML5";
static final String TVHTML5_CLIENT_VERSION = "7.20250122.15.00";
static final String TVHTML5_CLIENT_PLATFORM = "GAME_CONSOLE";
static final String TVHTML5_DEVICE_MAKE = "Sony";
static final String TVHTML5_DEVICE_MODEL_AND_OS_NAME = "PlayStation 4";
// CHECKSTYLE:OFF
static final String TVHTML5_USER_AGENT =
"Mozilla/5.0 (PlayStation; PlayStation 4/12.00) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15";
// CHECKSTYLE:ON
static final String WEB_REMIX_HARDCODED_CLIENT_VERSION = "1.20260121.03.00";

// WEB_EMBEDDED_PLAYER (YouTube embeds)

static final String WEB_EMBEDDED_CLIENT_ID = "56";
static final String WEB_EMBEDDED_CLIENT_NAME = "WEB_EMBEDDED_PLAYER";
static final String WEB_EMBEDDED_CLIENT_VERSION = "1.20250121.00.00";
static final String WEB_EMBEDDED_CLIENT_VERSION = "1.20260122.01.00";

// WEB_MUSIC_ANALYTICS (YouTube charts)

Expand All @@ -61,11 +49,11 @@ private ClientsConstants() {
*
* <p>
* It can be extracted by getting the latest release version of the app on
* <a href="https://apps.apple.com/us/app/youtube-watch-listen-stream/id544007664/">the App
* <a href="https://apps.apple.com/us/app/youtube/id544007664">the App
* Store page of the YouTube app</a>, in the {@code What’s New} section.
* </p>
*/
static final String IOS_CLIENT_VERSION = "20.03.02";
static final String IOS_CLIENT_VERSION = "21.03.2";

/**
* The device machine id for the iPhone 15 Pro Max, used to get 60fps with the {@code iOS}
Expand Down Expand Up @@ -93,7 +81,7 @@ private ClientsConstants() {
*
* @see #IOS_USER_AGENT_VERSION
*/
static final String IOS_OS_VERSION = "18.2.1.22C161";
static final String IOS_OS_VERSION = "18.7.2.22H124";

/**
* The iOS version to be used in the HTTP user agent for requests.
Expand All @@ -104,7 +92,7 @@ private ClientsConstants() {
*
* @see #IOS_OS_VERSION
*/
static final String IOS_USER_AGENT_VERSION = "18_2_1";
static final String IOS_USER_AGENT_VERSION = "18_7_2";

// ANDROID (Android YouTube app) client fields

Expand All @@ -120,5 +108,5 @@ private ClientsConstants() {
* such as <a href="https://www.apkmirror.com/apk/google-inc/youtube/">APKMirror</a>.
* </p>
*/
static final String ANDROID_CLIENT_VERSION = "19.28.35";
static final String ANDROID_CLIENT_VERSION = "21.03.36";
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public static InnertubeClientRequestInfo ofAndroidClient() {
new InnertubeClientRequestInfo.ClientInfo(ANDROID_CLIENT_NAME,
ANDROID_CLIENT_VERSION, ANDROID_CLIENT_ID, WATCH_CLIENT_SCREEN, null),
new InnertubeClientRequestInfo.DeviceInfo(MOBILE_CLIENT_PLATFORM, null, null,
"Android", "15", 35));
"Android", "16", 36));
}

@Nonnull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import static org.schabi.newpipe.extractor.services.youtube.ClientsConstants.IOS_CLIENT_VERSION;
import static org.schabi.newpipe.extractor.services.youtube.ClientsConstants.IOS_DEVICE_MODEL;
import static org.schabi.newpipe.extractor.services.youtube.ClientsConstants.IOS_USER_AGENT_VERSION;
import static org.schabi.newpipe.extractor.services.youtube.ClientsConstants.TVHTML5_USER_AGENT;
import static org.schabi.newpipe.extractor.services.youtube.ClientsConstants.WEB_CLIENT_ID;
import static org.schabi.newpipe.extractor.services.youtube.ClientsConstants.WEB_CLIENT_NAME;
import static org.schabi.newpipe.extractor.services.youtube.ClientsConstants.WEB_HARDCODED_CLIENT_VERSION;
Expand Down Expand Up @@ -1118,17 +1117,6 @@ public static String getIosUserAgent(@Nullable final Localization localization)
+ ")";
}

/**
* Get the user-agent string used as the user-agent for InnerTube requests with the HTML5 TV
* client.
*
* @return the user-agent used for InnerTube requests with the TVHTML5 client
*/
@Nonnull
public static String getTvHtml5UserAgent() {
return TVHTML5_USER_AGENT;
}

/**
* Returns a {@link Map} containing the required YouTube Music headers.
*/
Expand Down Expand Up @@ -1384,17 +1372,6 @@ public static boolean isWebEmbeddedPlayerStreamingUrl(@Nonnull final String url)
return Parser.isMatch(C_WEB_EMBEDDED_PLAYER_PATTERN, url);
}

/**
* Check if the streaming URL is a URL from the YouTube {@code TVHTML5} client.
*
* @param url the streaming URL on which check if it's a {@code TVHTML5}
* streaming URL.
* @return true if it's a {@code TVHTML5} streaming URL, false otherwise
*/
public static boolean isTvHtml5StreamingUrl(@Nonnull final String url) {
return Parser.isMatch(C_TVHTML5_PLAYER_PATTERN, url);
}

/**
* Check if the streaming URL is a URL from the YouTube {@code ANDROID} client.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static JsonObject getWebMetadataPlayerResponse(
.getBytes(StandardCharsets.UTF_8);

final String url = YOUTUBEI_V1_URL + PLAYER + "?" + DISABLE_PRETTY_PRINT_PARAMETER
+ "&$fields=microformat,playabilityStatus,storyboards,videoDetails";
+ "&$fields=microformat,videoDetails.thumbnail.thumbnails,videoDetails.videoId";

return JsonUtils.toJsonObject(getValidJsonResponseBody(
getDownloader().postWithContentTypeJson(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getAndroidUserAgent;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getIosUserAgent;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getOriginReferrerHeaders;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTvHtml5UserAgent;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isAndroidStreamingUrl;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isIosStreamingUrl;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isTvHtml5StreamingUrl;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebStreamingUrl;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isWebEmbeddedPlayerStreamingUrl;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
Expand Down Expand Up @@ -604,9 +602,7 @@ public static Response getInitializationResponse(@Nonnull String baseStreamingUr
@Nonnull final ItagItem itagItem,
final DeliveryType deliveryType)
throws CreationException {
final boolean isTvHtml5StreamingUrl = isTvHtml5StreamingUrl(baseStreamingUrl);
final boolean isHtml5StreamingUrl = isWebStreamingUrl(baseStreamingUrl)
|| isTvHtml5StreamingUrl
|| isWebEmbeddedPlayerStreamingUrl(baseStreamingUrl);
final boolean isAndroidStreamingUrl = isAndroidStreamingUrl(baseStreamingUrl);
final boolean isIosStreamingUrl = isIosStreamingUrl(baseStreamingUrl);
Expand All @@ -620,7 +616,7 @@ public static Response getInitializationResponse(@Nonnull String baseStreamingUr
final String mimeTypeExpected = itagItem.getMediaFormat().getMimeType();
if (!isNullOrEmpty(mimeTypeExpected)) {
return getStreamingWebUrlWithoutRedirects(downloader, baseStreamingUrl,
mimeTypeExpected, isTvHtml5StreamingUrl);
mimeTypeExpected);
}
} else if (isAndroidStreamingUrl || isIosStreamingUrl) {
try {
Expand Down Expand Up @@ -735,8 +731,6 @@ private static String appendRnSqParamsIfNeeded(@Nonnull final String baseStreami
* @param downloader the {@link Downloader} instance to be used
* @param streamingUrl the streaming URL which we are trying to get a streaming URL
* without any redirection on the network and/or IP used
* @param isTvHtml5StreamingUrl whether the streaming URL comes from TVHTML5 client, in
* order to use an appropriate HTTP User-Agent header
* @param responseMimeTypeExpected the response mime type expected from Google video servers
* @return the {@link Response} of the stream, which should have no redirections
*/
Expand All @@ -745,15 +739,11 @@ private static String appendRnSqParamsIfNeeded(@Nonnull final String baseStreami
private static Response getStreamingWebUrlWithoutRedirects(
@Nonnull final Downloader downloader,
@Nonnull String streamingUrl,
@Nonnull final String responseMimeTypeExpected,
final boolean isTvHtml5StreamingUrl)
@Nonnull final String responseMimeTypeExpected)
throws CreationException {
try {
final var headers = new HashMap<>(
getOriginReferrerHeaders("https://www.youtube.com"));
if (isTvHtml5StreamingUrl) {
headers.put("User-Agent", List.of(getTvHtml5UserAgent()));
}

String responseMimeType = "";

Expand Down
Loading
Loading