diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java index 5b9ae5801a..979ce85eea 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java @@ -926,6 +926,10 @@ private void fetchAndroidMobileJsonPlayer(@Nonnull final ContentCountry contentC mobileBody, localization, "&t=" + generateTParameter() + "&id=" + videoId); + if (isPlayerResponseNotValid(androidPlayerResponse, videoId)) { + return; + } + final JsonObject streamingData = androidPlayerResponse.getObject(STREAMING_DATA); if (!isNullOrEmpty(streamingData)) { androidStreamingData = streamingData; @@ -957,6 +961,10 @@ private void fetchIosMobileJsonPlayer(@Nonnull final ContentCountry contentCount mobileBody, localization, "&t=" + generateTParameter() + "&id=" + videoId); + if (isPlayerResponseNotValid(iosPlayerResponse, videoId)) { + return; + } + final JsonObject streamingData = iosPlayerResponse.getObject(STREAMING_DATA); if (!isNullOrEmpty(streamingData)) { iosStreamingData = streamingData; @@ -995,6 +1003,38 @@ private void fetchTvHtml5EmbedJsonPlayer(@Nonnull final ContentCountry contentCo } } + /** + * Checks whether an additional player response is not valid. + * + *

+ * If YouTube detect that requests come from a third party client, they may replace the real + * player response by another one of a video saying that this content is not available on this + * app and to watch it on the latest version of YouTube. + *

+ * + *

+ * We can detect this by checking whether the video ID of the player response returned is the + * same as the one requested by the extractor. + *

+ * + *

+ * This behavior has been already observed on the {@code ANDROID} client, see + * + * https://github.com/TeamNewPipe/NewPipe/issues/8713. + *

+ * + * @param additionalPlayerResponse an additional response to the one of the {@code HTML5} + * client used + * @param videoId the video ID of the content requested + * @return whether the video ID of the player response is not equal to the one requested + */ + private static boolean isPlayerResponseNotValid( + @Nonnull final JsonObject additionalPlayerResponse, + @Nonnull final String videoId) { + return !videoId.equals(additionalPlayerResponse.getObject("videoDetails") + .getString("videoId", "")); + } + private static void storePlayerJs() throws ParsingException { try { playerCode = YoutubeJavaScriptExtractor.extractJavaScriptCode();