@@ -205,6 +205,7 @@ private YoutubeParsingHelper() {
205205 private static String [] youtubeMusicKey ;
206206
207207 private static boolean keyAndVersionExtracted = false ;
208+ private static final Object KEY_AND_VERSION_EXTRACTED_LOCK = new Object ();
208209 @ SuppressWarnings ("OptionalUsedAsFieldOrParameterType" )
209210 private static Optional <Boolean > hardcodedClientVersionAndKeyValid = Optional .empty ();
210211
@@ -575,8 +576,24 @@ public static boolean areHardcodedClientVersionAndKeyValid()
575576
576577 private static void extractClientVersionAndKeyFromSwJs ()
577578 throws IOException , ExtractionException {
578- if (keyAndVersionExtracted ) {
579- return ;
579+ synchronized (KEY_AND_VERSION_EXTRACTED_LOCK ) {
580+ if (keyAndVersionExtracted ) {
581+ return ;
582+ }
583+ final String url = "https://www.youtube.com/sw.js" ;
584+ final Map <String , List <String >> headers = new HashMap <>();
585+ headers .put ("Origin" , singletonList ("https://www.youtube.com" ));
586+ headers .put ("Referer" , singletonList ("https://www.youtube.com" ));
587+ final String response = getDownloader ().get (url , headers ).responseBody ();
588+ try {
589+ clientVersion = getStringResultFromRegexArray (response ,
590+ INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES , 1 );
591+ key = getStringResultFromRegexArray (response , INNERTUBE_API_KEY_REGEXES , 1 );
592+ } catch (final Parser .RegexException e ) {
593+ throw new ParsingException ("Could not extract YouTube WEB InnerTube client version "
594+ + "and API key from sw.js" , e );
595+ }
596+ keyAndVersionExtracted = true ;
580597 }
581598 final String url = "https://www.youtube.com/sw.js" ;
582599 final var headers = getOriginReferrerHeaders ("https://www.youtube.com" );
@@ -594,61 +611,66 @@ private static void extractClientVersionAndKeyFromSwJs()
594611
595612 private static void extractClientVersionAndKeyFromHtmlSearchResultsPage ()
596613 throws IOException , ExtractionException {
597- // Don't extract the client version and the InnerTube key if it has been already extracted
598- if (keyAndVersionExtracted ) {
599- return ;
600- }
601614
602- // Don't provide a search term in order to have a smaller response
603- final String url = "https://www.youtube.com/results?search_query=&ucbcb=1" ;
604- final String html = getDownloader ().get (url , getCookieHeader ()).responseBody ();
605- final JsonObject initialData = getInitialData (html );
606- final JsonArray serviceTrackingParams = initialData .getObject ("responseContext" )
607- .getArray ("serviceTrackingParams" );
615+ synchronized (KEY_AND_VERSION_EXTRACTED_LOCK ) {
608616
609- // Try to get version from initial data first
610- final Stream <JsonObject > serviceTrackingParamsStream = serviceTrackingParams .stream ()
611- .filter (JsonObject .class ::isInstance )
612- .map (JsonObject .class ::cast );
617+ // Don't extract the client version and the InnerTube key
618+ // if it has been already extracted
619+ if (keyAndVersionExtracted ) {
620+ return ;
621+ }
622+
623+ // Don't provide a search term in order to have a smaller response
624+ final String url = "https://www.youtube.com/results?search_query=&ucbcb=1" ;
625+ final String html = getDownloader ().get (url , getCookieHeader ()).responseBody ();
626+ final JsonObject initialData = getInitialData (html );
627+ final JsonArray serviceTrackingParams = initialData .getObject ("responseContext" )
628+ .getArray ("serviceTrackingParams" );
629+
630+ // Try to get version from initial data first
631+ final Stream <JsonObject > serviceTrackingParamsStream = serviceTrackingParams .stream ()
632+ .filter (JsonObject .class ::isInstance )
633+ .map (JsonObject .class ::cast );
634+
635+ clientVersion = getClientVersionFromServiceTrackingParam (
636+ serviceTrackingParamsStream , "CSI" , "cver" );
637+
638+ if (clientVersion == null ) {
639+ try {
640+ clientVersion = getStringResultFromRegexArray (html ,
641+ INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES , 1 );
642+ } catch (final Parser .RegexException ignored ) {
643+ }
644+ }
613645
614- clientVersion = getClientVersionFromServiceTrackingParam (
615- serviceTrackingParamsStream , "CSI" , "cver" );
646+ // Fallback to get a shortened client version which does not contain the last two
647+ // digits
648+ if (isNullOrEmpty (clientVersion )) {
649+ clientVersion = getClientVersionFromServiceTrackingParam (
650+ serviceTrackingParamsStream , "ECATCHER" , "client.version" );
651+ }
616652
617- if (clientVersion == null ) {
618653 try {
619- clientVersion = getStringResultFromRegexArray (html ,
620- INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES , 1 );
654+ key = getStringResultFromRegexArray (html , INNERTUBE_API_KEY_REGEXES , 1 );
621655 } catch (final Parser .RegexException ignored ) {
622656 }
623- }
624-
625- // Fallback to get a shortened client version which does not contain the last two
626- // digits
627- if (isNullOrEmpty (clientVersion )) {
628- clientVersion = getClientVersionFromServiceTrackingParam (
629- serviceTrackingParamsStream , "ECATCHER" , "client.version" );
630- }
631657
632- try {
633- key = getStringResultFromRegexArray (html , INNERTUBE_API_KEY_REGEXES , 1 );
634- } catch (final Parser .RegexException ignored ) {
635- }
658+ if (isNullOrEmpty (key )) {
659+ throw new ParsingException (
660+ // CHECKSTYLE:OFF
661+ "Could not extract YouTube WEB InnerTube API key from HTML search results page" );
662+ // CHECKSTYLE:ON
663+ }
636664
637- if (isNullOrEmpty ( key ) ) {
638- throw new ParsingException (
639- // CHECKSTYLE:OFF
640- "Could not extract YouTube WEB InnerTube API key from HTML search results page" );
641- // CHECKSTYLE:ON
642- }
665+ if (clientVersion == null ) {
666+ throw new ParsingException (
667+ // CHECKSTYLE:OFF
668+ "Could not extract YouTube WEB InnerTube client version from HTML search results page" );
669+ // CHECKSTYLE:ON
670+ }
643671
644- if (clientVersion == null ) {
645- throw new ParsingException (
646- // CHECKSTYLE:OFF
647- "Could not extract YouTube WEB InnerTube client version from HTML search results page" );
648- // CHECKSTYLE:ON
672+ keyAndVersionExtracted = true ;
649673 }
650-
651- keyAndVersionExtracted = true ;
652674 }
653675
654676 @ Nullable
0 commit comments