Skip to content

Commit f345f66

Browse files
committed
Extract YouTube's key
1 parent 4c987a5 commit f345f66

2 files changed

Lines changed: 55 additions & 33 deletions

File tree

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

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ private YoutubeParsingHelper() {
6464
private static final String HARDCODED_CLIENT_VERSION = "2.20200214.04.00";
6565
private static String clientVersion;
6666

67+
private static String key;
68+
6769
private static final String[] HARDCODED_YOUTUBE_MUSIC_KEYS = {"AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30", "67", "0.1"};
6870
private static String[] youtubeMusicKeys;
6971

@@ -214,39 +216,31 @@ public static boolean isHardcodedClientVersionValid() throws IOException, Extrac
214216
return response.length() > 50; // ensure to have a valid response
215217
}
216218

217-
/**
218-
* Get the client version from a page
219-
* @return
220-
* @throws ParsingException
221-
*/
222-
public static String getClientVersion() throws IOException, ExtractionException {
223-
if (!isNullOrEmpty(clientVersion)) return clientVersion;
224-
if (isHardcodedClientVersionValid()) return clientVersion = HARDCODED_CLIENT_VERSION;
225-
219+
private static void getClientVersionAndKey() throws IOException, ExtractionException {
226220
final String url = "https://www.youtube.com/results?search_query=test";
227221
final String html = getDownloader().get(url).responseBody();
228-
JsonObject initialData = getInitialData(html);
229-
JsonArray serviceTrackingParams = initialData.getObject("responseContext").getArray("serviceTrackingParams");
222+
final JsonObject initialData = getInitialData(html);
223+
final JsonArray serviceTrackingParams = initialData.getObject("responseContext").getArray("serviceTrackingParams");
230224
String shortClientVersion = null;
231225

232226
// try to get version from initial data first
233-
for (Object service : serviceTrackingParams) {
234-
JsonObject s = (JsonObject) service;
227+
for (final Object service : serviceTrackingParams) {
228+
final JsonObject s = (JsonObject) service;
235229
if (s.getString("service").equals("CSI")) {
236-
JsonArray params = s.getArray("params");
237-
for (Object param : params) {
238-
JsonObject p = (JsonObject) param;
239-
String key = p.getString("key");
230+
final JsonArray params = s.getArray("params");
231+
for (final Object param : params) {
232+
final JsonObject p = (JsonObject) param;
233+
final String key = p.getString("key");
240234
if (key != null && key.equals("cver")) {
241-
return clientVersion = p.getString("value");
235+
clientVersion = p.getString("value");
242236
}
243237
}
244238
} else if (s.getString("service").equals("ECATCHER")) {
245239
// fallback to get a shortened client version which does not contain the last two digits
246-
JsonArray params = s.getArray("params");
247-
for (Object param : params) {
248-
JsonObject p = (JsonObject) param;
249-
String key = p.getString("key");
240+
final JsonArray params = s.getArray("params");
241+
for (final Object param : params) {
242+
final JsonObject p = (JsonObject) param;
243+
final String key = p.getString("key");
250244
if (key != null && key.equals("client.version")) {
251245
shortClientVersion = p.getString("value");
252246
}
@@ -255,26 +249,54 @@ public static String getClientVersion() throws IOException, ExtractionException
255249
}
256250

257251
String contextClientVersion;
258-
String[] patterns = {
252+
final String[] patterns = {
259253
"INNERTUBE_CONTEXT_CLIENT_VERSION\":\"([0-9\\.]+?)\"",
260254
"innertube_context_client_version\":\"([0-9\\.]+?)\"",
261255
"client.version=([0-9\\.]+)"
262256
};
263-
for (String pattern : patterns) {
257+
for (final String pattern : patterns) {
264258
try {
265259
contextClientVersion = Parser.matchGroup1(pattern, html);
266260
if (!isNullOrEmpty(contextClientVersion)) {
267-
return clientVersion = contextClientVersion;
261+
clientVersion = contextClientVersion;
268262
}
269-
} catch (Exception ignored) {
270-
}
263+
} catch (Parser.RegexException ignored) { }
271264
}
272265

273266
if (shortClientVersion != null) {
274-
return clientVersion = shortClientVersion;
267+
clientVersion = shortClientVersion;
268+
}
269+
270+
try {
271+
key = Parser.matchGroup1("INNERTUBE_API_KEY\":\"([0-9a-zA-Z_-]+?)\"", html);
272+
} catch (Parser.RegexException e) {
273+
try {
274+
key = Parser.matchGroup1("innertubeApiKey\":\"([0-9a-zA-Z_-]+?)\"", html);
275+
} catch (Parser.RegexException ignored) { }
275276
}
277+
}
278+
279+
/**
280+
* Get the client version
281+
*/
282+
public static String getClientVersion() throws IOException, ExtractionException {
283+
if (!isNullOrEmpty(clientVersion)) return clientVersion;
284+
if (isHardcodedClientVersionValid()) return clientVersion = HARDCODED_CLIENT_VERSION;
285+
286+
getClientVersionAndKey();
287+
if (isNullOrEmpty(key)) throw new ParsingException("Could not extract client version");
288+
return clientVersion;
289+
}
290+
291+
/**
292+
* Get the key
293+
*/
294+
public static String getKey() throws IOException, ExtractionException {
295+
if (!isNullOrEmpty(key)) return key;
276296

277-
throw new ParsingException("Could not get client version");
297+
getClientVersionAndKey();
298+
if (isNullOrEmpty(key)) throw new ParsingException("Could not extract key");
299+
return key;
278300
}
279301

280302
public static boolean areHardcodedYoutubeMusicKeysValid() throws IOException, ReCaptchaException {

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getClientVersion;
3030
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonResponse;
31+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey;
3132
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
3233
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getValidJsonResponseBody;
3334
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
@@ -107,7 +108,7 @@ public boolean isCorrectedSearch() {
107108

108109
@Nonnull
109110
@Override
110-
public InfoItemsPage<InfoItem> getInitialPage() throws ExtractionException {
111+
public InfoItemsPage<InfoItem> getInitialPage() throws IOException, ExtractionException {
111112
final InfoItemsSearchCollector collector = new InfoItemsSearchCollector(getServiceId());
112113

113114
final JsonArray sections = initialData.getObject("contents").getObject("twoColumnSearchResultsRenderer")
@@ -221,16 +222,15 @@ private Page getNextPageFrom(final JsonArray continuations) throws ParsingExcept
221222
+ "&itct=" + clickTrackingParams);
222223
}
223224

224-
private Page getNewNextPageFrom(final JsonObject continuationItemRenderer) {
225+
private Page getNewNextPageFrom(final JsonObject continuationItemRenderer) throws IOException, ExtractionException {
225226
if (isNullOrEmpty(continuationItemRenderer)) {
226227
return null;
227228
}
228229

229230
final String token = continuationItemRenderer.getObject("continuationEndpoint")
230231
.getObject("continuationCommand").getString("token");
231232

232-
// FIXME: Key needs to be extracted
233-
final String url = "https://www.youtube.com/youtubei/v1/search?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
233+
final String url = "https://www.youtube.com/youtubei/v1/search?key=" + getKey();
234234

235235
return new Page(url, token);
236236
}

0 commit comments

Comments
 (0)