Merge pull request #1397 from FineFindus/fix/multiple-uploaders-url
Some checks failed
CI / build-and-test (push) Has been cancelled

[YouTube] Extract uploader URL for videos with multiple uploaders
This commit is contained in:
Tobi
2025-11-03 07:26:37 -08:00
committed by GitHub
14 changed files with 3130 additions and 12 deletions

View File

@@ -759,6 +759,22 @@ public final class YoutubeParsingHelper {
.getString("playlistId");
}
if (navigationEndpoint.has("showDialogCommand")) {
try {
final JsonArray listItems = JsonUtils.getArray(navigationEndpoint,
"showDialogCommand.panelLoadingStrategy.inlineContent.dialogViewModel"
+ ".customContent.listViewModel.listItems");
// the first item seems to always be the channel that actually uploaded the video,
// i.e. it appears in their video feed
final JsonObject command = JsonUtils.getObject(listItems.getObject(0),
"listItemViewModel.rendererContext.commandContext.onTap.innertubeCommand");
return getUrlFromNavigationEndpoint(command);
} catch (final ParsingException p) {
}
}
if (navigationEndpoint.has("commandMetadata")) {
final JsonObject metadata = navigationEndpoint.getObject("commandMetadata")
.getObject("webCommandMetadata");
@@ -1572,4 +1588,24 @@ public final class YoutubeParsingHelper {
return builder;
}
/**
* Gets the first collaborator, which is the channel that owns the video,
* i.e. the video is displayed on their channel page.
*
* @param navigationEndpoint JSON object for the navigationEndpoint
* @return The first collaborator in the JSON object or {@code null}
*/
@Nullable
public static JsonObject getFirstCollaborator(final JsonObject navigationEndpoint)
throws ParsingException {
try {
// CHECKSTYLE:OFF
final JsonArray listItems = JsonUtils.getArray(navigationEndpoint, "showDialogCommand.panelLoadingStrategy.inlineContent.dialogViewModel.customContent.listViewModel.listItems");
// CHECKSTYLE:ON
return listItems.getObject(0).getObject("listItemViewModel");
} catch (final ParsingException e) {
return null;
}
}
}

View File

@@ -541,23 +541,47 @@ public class YoutubeStreamExtractor extends StreamExtractor {
@Override
public boolean isUploaderVerified() throws ParsingException {
return YoutubeParsingHelper.isVerified(
getVideoSecondaryInfoRenderer()
final JsonObject videoOwnerRenderer = getVideoSecondaryInfoRenderer()
.getObject("owner")
.getObject("videoOwnerRenderer")
.getArray("badges"));
.getObject("videoOwnerRenderer");
if (videoOwnerRenderer.has("badges")) {
return YoutubeParsingHelper.isVerified(videoOwnerRenderer
.getArray("badges"));
}
final JsonObject channel = YoutubeParsingHelper.getFirstCollaborator(
videoOwnerRenderer.getObject("navigationEndpoint"));
if (channel == null) {
return false;
}
return YoutubeParsingHelper.hasArtistOrVerifiedIconBadgeAttachment(
channel.getObject("title").getArray("attachmentRuns"));
}
@Nonnull
@Override
public List<Image> getUploaderAvatars() throws ParsingException {
assertPageFetched();
final JsonObject owner = getVideoSecondaryInfoRenderer().getObject("owner")
.getObject("videoOwnerRenderer");
final List<Image> imageList = getImagesFromThumbnailsArray(
getVideoSecondaryInfoRenderer().getObject("owner")
.getObject("videoOwnerRenderer")
.getObject("thumbnail")
.getArray("thumbnails"));
final List<Image> imageList;
if (owner.has("avatarStack")) {
imageList = getImagesFromThumbnailsArray(
owner.getObject("avatarStack").getObject("avatarStackViewModel")
.getArray("avatars")
// only consider the first collaborator, which is the video owner
.getObject(0)
.getObject("avatarViewModel")
.getObject("image")
.getArray("sources"));
} else {
imageList = getImagesFromThumbnailsArray(
owner.getObject("thumbnail").getArray("thumbnails"));
}
if (imageList.isEmpty() && ageLimit == NO_AGE_LIMIT) {
throw new ParsingException("Could not get uploader avatars");
@@ -570,12 +594,24 @@ public class YoutubeStreamExtractor extends StreamExtractor {
public long getUploaderSubscriberCount() throws ParsingException {
final JsonObject videoOwnerRenderer = JsonUtils.getObject(videoSecondaryInfoRenderer,
"owner.videoOwnerRenderer");
if (!videoOwnerRenderer.has("subscriberCountText")) {
String subscriberCountText = null;
if (videoOwnerRenderer.has("subscriberCountText")) {
subscriberCountText = getTextFromObject(videoOwnerRenderer
.getObject("subscriberCountText"));
} else {
final String content = YoutubeParsingHelper.getFirstCollaborator(
videoOwnerRenderer.getObject("navigationEndpoint")
).getObject("subtitle").getString("content");
subscriberCountText = content.split("")[1];
}
if (isNullOrEmpty(subscriberCountText)) {
return UNKNOWN_SUBSCRIBER_COUNT;
}
try {
return Utils.mixedNumberWordToLong(getTextFromObject(videoOwnerRenderer
.getObject("subscriberCountText")));
return Utils.mixedNumberWordToLong(subscriberCountText);
} catch (final NumberFormatException e) {
throw new ParsingException("Could not get uploader subscriber count", e);
}

View File

@@ -335,6 +335,56 @@ public class YoutubeSearchExtractorTest {
}
}
public static class MultipleUploader extends DefaultSearchExtractorTest implements InitYoutubeTest {
private static final String QUERY = "Nxk6aRHi664";
@Override
protected SearchExtractor createExtractor() throws Exception {
return YouTube.getSearchExtractor(QUERY, singletonList(VIDEOS), "");
}
@Override public StreamingService expectedService() { return YouTube; }
@Override public String expectedName() { return QUERY; }
@Override public String expectedId() { return QUERY; }
@Override public String expectedUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
@Override public String expectedOriginalUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
@Override public String expectedSearchString() { return QUERY; }
@Nullable @Override public String expectedSearchSuggestion() { return null; }
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
@Test
void testUploaderName() throws IOException, ExtractionException {
final List<InfoItem> items = extractor().getInitialPage().getItems();
assertEquals("Le Vortex - ARTE and Thomas Gauthier",
((StreamInfoItem) items.get(0)).getUploaderName());
}
@Test
void testUploaderUrl() throws IOException, ExtractionException {
final List<InfoItem> items = extractor().getInitialPage().getItems();
assertEquals("https://www.youtube.com/channel/UCZxLew-WXWm5dhRZBgEFl-Q",
((StreamInfoItem) items.get(0)).getUploaderUrl());
}
@Test
void testUploaderAvatars() throws IOException, ExtractionException {
final List<InfoItem> items = extractor().getInitialPage().getItems();
assertNotNull(((StreamInfoItem) items.get(0)).getUploaderAvatars());
}
@Disabled("Irrelevant - sometimes suggestions show up, sometimes not")
@Override
public void testSearchSuggestion() throws Exception {
super.testSearchSuggestion();
}
@Disabled("Irrelevant - sometimes suggestions show up, sometimes not")
@Override
public void testMoreRelatedItems() throws Exception {
super.testMoreRelatedItems();
}
}
public static class ShortFormContent extends DefaultSearchExtractorTest implements InitYoutubeTest {
private static final String QUERY = "#shorts";

View File

@@ -0,0 +1,66 @@
package org.schabi.newpipe.extractor.services.youtube.stream;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertNotEmpty;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestImageCollection;
import org.junit.jupiter.api.Disabled;
import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.services.DefaultStreamExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.InitYoutubeTest;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.stream.StreamType;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
public class YoutubeStreamExtractorCollaboratorsTest extends DefaultStreamExtractorTest
implements InitYoutubeTest {
private static final String ID = "3sbYbckT1VY";
private static final String URL = YoutubeStreamExtractorDefaultTest.BASE_URL + ID;
@Override
protected StreamExtractor createExtractor() throws Exception {
return YouTube.getStreamExtractor(URL);
}
@Override public StreamingService expectedService() { return YouTube; }
@Override public String expectedName() { return "Engineers vs Pumpkin Carving 2.0"; }
@Override public String expectedId() { return ID; }
@Override public String expectedUrlContains() { return YoutubeStreamExtractorDefaultTest.BASE_URL + ID; }
@Override public String expectedOriginalUrlContains() { return URL; }
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
@Override public String expectedUploaderName() { return "CrunchLabs"; }
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UC513PdAP2-jWkJunTh5kXRw"; }
@Override public long expectedUploaderSubscriberCountAtLeast() { return 227_0000; }
@Override public boolean expectedUploaderVerified() { return true; }
@Override public boolean expectedDescriptionIsEmpty() { return false; }
@Override public List<String> expectedDescriptionContains() { return Collections.emptyList(); }
@Override public long expectedLength() { return 696; }
@Override public long expectedViewCountAtLeast() { return 1_400_000; }
@Nullable @Override public String expectedUploadDate() { return "2025-10-25 15:33:05.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2025-10-25T08:33:05-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 20_000; }
@Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public boolean expectedHasSubtitles() { return true; }
@Override public boolean expectedHasFrames() { return true; }
@Override public String expectedCategory() { return "Science & Technology"; }
@Override public String expectedLicence() { return "YouTube licence"; }
@Override
public List<String> expectedTags() {
return Collections.emptyList();
}
@Override
public void testUploaderAvatars() throws Exception {
List<Image> avatars = extractor().getUploaderAvatars();
assertNotEmpty(avatars);
defaultTestImageCollection(avatars);
}
}

View File

@@ -0,0 +1,97 @@
{
"request": {
"httpMethod": "GET",
"url": "https://www.youtube.com/sw.js",
"headers": {
"Referer": [
"https://www.youtube.com"
],
"Origin": [
"https://www.youtube.com"
],
"Accept-Language": [
"en-GB, en;q\u003d0.9"
]
},
"localization": {
"languageCode": "en",
"countryCode": "GB"
}
},
"response": {
"responseCode": 200,
"responseMessage": "",
"responseHeaders": {
"access-control-allow-credentials": [
"true"
],
"access-control-allow-origin": [
"https://www.youtube.com"
],
"alt-svc": [
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000"
],
"cache-control": [
"private, max-age\u003d0"
],
"content-security-policy": [
"require-trusted-types-for \u0027script\u0027"
],
"content-security-policy-report-only": [
"script-src \u0027unsafe-eval\u0027 \u0027self\u0027 \u0027unsafe-inline\u0027 https://www.google.com https://apis.google.com https://ssl.gstatic.com https://www.gstatic.com https://www.googletagmanager.com https://www.google-analytics.com https://*.youtube.com https://*.google.com https://*.gstatic.com https://youtube.com https://www.youtube.com https://google.com https://*.doubleclick.net https://*.googleapis.com https://www.googleadservices.com https://tpc.googlesyndication.com https://www.youtubekids.com https://www.youtube-nocookie.com https://www.youtubeeducation.com https://www-onepick-opensocial.googleusercontent.com;report-uri /cspreport/allowlist"
],
"content-type": [
"text/javascript; charset\u003dutf-8"
],
"cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\""
],
"date": [
"Fri, 31 Oct 2025 15:26:13 GMT"
],
"document-policy": [
"include-js-call-stacks-in-crash-reports"
],
"expires": [
"Fri, 31 Oct 2025 15:26:13 GMT"
],
"origin-trial": [
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9",
"AiDEBptUfVeO93q48VdVMe/ubupazdAl8AaHP+NBzdnW8quUcHdzJUyGSfrmtpKJu7EOvwRp9ug2rEo3XU+WMAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJEZXZpY2VCb3VuZFNlc3Npb25DcmVkZW50aWFsczIiLCJleHBpcnkiOjE3NzQzMTA0MDAsImlzU3ViZG9tYWluIjp0cnVlfQ\u003d\u003d"
],
"p3p": [
"CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\""
],
"permissions-policy": [
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-form-factors\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
],
"report-to": [
"{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}"
],
"reporting-endpoints": [
"default\u003d\"/web-reports?context\u003deJwNzmtsjGkYxnFv_3Z0Z6bzzvvcjxQlbLU2sabaJiWOH0irS4Zu4jw2bTEtQquzM0MtiU1JEMdYp9o6bHZV1CllJXRtgw_OuqF0lwqpD9IQrETVsft8-H24k_u6crmbvyjuWmKl5ZdZrm-XWidXVVhzvo5YuU0_WBvzolbHoah1rCFqPR8Qt0KpcWv33bi1-NFya59_ZsLyPjMTGma7KSlx82aPm_9a3VS-dBP6xsOdiR6eT_ZwptZDQ72Hh089xEJeXhV5yYl5Ke_w0l6QxPk9SQyZ6uPwWR8Fl31sM1588pGWZbNqhM2wMTbHJ9jEwzaeuE31epusXTaJB22Sr9msb7M5n-YnsciP27i910-PE35a3_oZ9d7P9-JQlOPwyzSHh4UOwVKHlSsd1hiT1jqM2-wwdqdD4xGHAXUOKccdpNmhb7tDW6eD70tF_lDFipGK-3mKromKYEjRK66wVivUTsWCWsUiY4VRZVxsVIy5pUhpUoy-rfjqriK9RVH_RJHcYbKdig2fFS0uodkjDO0pBPsYKUJdf0FShfx0Yb5RmyEEcoR_RwkV44XioBCbInQae2cL40PCwLDJlQrucmG78ahCWBsxd5VQsk6YtUPI2CX8US2sqRF8B4Sag8KWX4V-v4vZLVyoExKOCleNP08Jj88KReeEk5eE6BVh_1Xzc134-4bw3U3T3SxYLULeP0KlkfzAbDbuGaWtQrfHJtMmbHoqpD8Tfn4tHO0QkjqFd0buO-Evo91oei98_GA2fhQiXcL07hq8mp98mqijuag1h3trXAM1wUGaQ4M104do6odrto3VVOVqTk_WVM_QvC3U_JjSzaW8iTuObL_i8m9t3PSblRqoLI9FY3PDGcvCcwMlkfKyaCBcNj8wL7IwunBe8eLC7MzsnKzM7BEZWZmFSzP_B5923l0\""
],
"server": [
"ESF"
],
"set-cookie": [
"YSC\u003dEPX_t6VvDa8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 04-Feb-2023 15:26:13 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
],
"strict-transport-security": [
"max-age\u003d31536000"
],
"x-content-type-options": [
"nosniff"
],
"x-frame-options": [
"SAMEORIGIN"
],
"x-xss-protection": [
"0"
]
},
"responseBody": "\n self.addEventListener(\u0027install\u0027, event \u003d\u003e {\n event.waitUntil(self.skipWaiting());\n });\n self.addEventListener(\u0027activate\u0027, event \u003d\u003e {\n event.waitUntil(\n self.clients.claim().then(() \u003d\u003e self.registration.unregister()));\n });\n ",
"latestUrl": "https://www.youtube.com/sw.js"
}
}

View File

@@ -0,0 +1,101 @@
{
"request": {
"httpMethod": "GET",
"url": "https://www.youtube.com/sw.js",
"headers": {
"Referer": [
"https://www.youtube.com"
],
"Origin": [
"https://www.youtube.com"
],
"Accept-Language": [
"en-GB, en;q\u003d0.9"
]
},
"localization": {
"languageCode": "en",
"countryCode": "GB"
}
},
"response": {
"responseCode": 200,
"responseMessage": "",
"responseHeaders": {
"accept-ch": [
"Device-Memory"
],
"access-control-allow-credentials": [
"true"
],
"access-control-allow-origin": [
"https://www.youtube.com"
],
"alt-svc": [
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000"
],
"cache-control": [
"private, max-age\u003d0"
],
"content-security-policy": [
"script-src \u0027unsafe-eval\u0027 \u0027self\u0027 \u0027unsafe-inline\u0027 https://www.google.com https://apis.google.com https://ssl.gstatic.com https://www.gstatic.com https://www.googletagmanager.com https://www.google-analytics.com https://*.youtube.com https://*.google.com https://*.gstatic.com https://youtube.com https://www.youtube.com https://google.com https://*.doubleclick.net https://*.googleapis.com https://www.googleadservices.com https://tpc.googlesyndication.com https://www.youtubekids.com https://www.youtube-nocookie.com https://www.youtubeeducation.com https://www-onepick-opensocial.googleusercontent.com;report-uri /cspreport/allowlist",
"require-trusted-types-for \u0027script\u0027"
],
"content-type": [
"text/javascript; charset\u003dutf-8"
],
"cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\""
],
"date": [
"Fri, 31 Oct 2025 18:29:12 GMT"
],
"document-policy": [
"include-js-call-stacks-in-crash-reports"
],
"expires": [
"Fri, 31 Oct 2025 18:29:12 GMT"
],
"origin-trial": [
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9",
"AiDEBptUfVeO93q48VdVMe/ubupazdAl8AaHP+NBzdnW8quUcHdzJUyGSfrmtpKJu7EOvwRp9ug2rEo3XU+WMAMAAAB2eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJEZXZpY2VCb3VuZFNlc3Npb25DcmVkZW50aWFsczIiLCJleHBpcnkiOjE3NzQzMTA0MDAsImlzU3ViZG9tYWluIjp0cnVlfQ\u003d\u003d"
],
"p3p": [
"CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\""
],
"permissions-policy": [
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-form-factors\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
],
"report-to": [
"{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}"
],
"reporting-endpoints": [
"default\u003d\"/web-reports?context\u003deJwNz1tMVHcQx3EOX0vonmXPnv8cY5UmVgRNtLsC8RJr9UEj3rJoTDXKSgB1VyXIZd1dUWnVqIk2VmO8ArWtfXCN92AwUkLR-NB6xSgG20IxvljUqG0irpeW_h8-yUwm88uMq_uD8oG1RvbsSuP8lzVG8eiIMbNjnbG7IGr0H48aZ1qjxrNP4kYwK24cuR83Knprje-8S1Jrhy1JbS1yEQ67eFXv4u9uF7UvXATHmtyba_Ks0KR8mcnFhElrk0nPY5NY0M3LUjfjY26q-t30LcigrT6DT7_wcKLFw4JfPOzTnv_rITvPom6yxcSpFmdnWcRDFmbcomGXRd5hi_RjFlkJiyHXLdqyvXwW8JJe6sWl3W3U9Tkv3a-9THnrpVhsvl1k01NiE1hlU1dns12bt8Nm-h6baYds2k_aZJ61kU6bol6bj_tsHiVtPB8q5oxT_F6gGJirSCxUBIKKj-KKlC0KdUixOqEo1yq0ai2ibdS-0jZr32hX2xVTbysyOxSf31WMuK_I6dI5ScXX_ym60oROUxg3WJg_TAhkCqeGC5IlzM4RVmoJv-CbIPw2RaiZIZQFhNh8Iak1FgkzgsLIkDBHO71KcFUJ-7U_a4QdEd1vE8I7haUHBf9hYWO90NwgbD8qeH4Qjh4T9v4obEoIV04JnBauaW0XhIctQulPwvmrwvfX9PyGcOemsPCWzu0UUruEggfCBm3IH_pmrUsLdwspD_XOIyH0WNit5TwVDvyj_-sXMpLCG63gjfCz9pfW8Vaw3gnvNf97ITIgLB7kgNthq8chajtcdhxODHXYPNwhbaRDYJTD8TEOTZMcts10aC502JSZkqbc6cmB_b-meS_tfdJAlm9DVSwaWx7yrw8t94UjVZVRX6hypW9FZE10zYqyipL83PwJebn5k_15uSXVuf8D6xjhyA\""
],
"server": [
"ESF"
],
"set-cookie": [
"YSC\u003dcZjnCZBaO0U; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 04-Feb-2023 18:29:12 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
],
"strict-transport-security": [
"max-age\u003d31536000"
],
"vary": [
"Device-Memory"
],
"x-content-type-options": [
"nosniff"
],
"x-frame-options": [
"SAMEORIGIN"
],
"x-xss-protection": [
"0"
]
},
"responseBody": "\n self.addEventListener(\u0027install\u0027, event \u003d\u003e {\n event.waitUntil(self.skipWaiting());\n });\n self.addEventListener(\u0027activate\u0027, event \u003d\u003e {\n event.waitUntil(\n self.clients.claim().then(() \u003d\u003e self.registration.unregister()));\n });\n ",
"latestUrl": "https://www.youtube.com/sw.js"
}
}

View File

@@ -0,0 +1,324 @@
{
"request": {
"httpMethod": "POST",
"url": "https://www.youtube.com/youtubei/v1/visitor_id?prettyPrint\u003dfalse",
"headers": {
"Referer": [
"https://www.youtube.com"
],
"Origin": [
"https://www.youtube.com"
],
"Cookie": [
"SOCS\u003dCAE\u003d"
],
"X-YouTube-Client-Version": [
"2.20251030.01.00"
],
"X-YouTube-Client-Name": [
"1"
],
"Content-Type": [
"application/json"
],
"Accept-Language": [
"en-GB, en;q\u003d0.9"
]
},
"dataToSend": [
123,
34,
99,
111,
110,
116,
101,
120,
116,
34,
58,
123,
34,
99,
108,
105,
101,
110,
116,
34,
58,
123,
34,
99,
108,
105,
101,
110,
116,
78,
97,
109,
101,
34,
58,
34,
87,
69,
66,
34,
44,
34,
99,
108,
105,
101,
110,
116,
86,
101,
114,
115,
105,
111,
110,
34,
58,
34,
50,
46,
50,
48,
50,
53,
49,
48,
51,
48,
46,
48,
49,
46,
48,
48,
34,
44,
34,
99,
108,
105,
101,
110,
116,
83,
99,
114,
101,
101,
110,
34,
58,
34,
87,
65,
84,
67,
72,
34,
44,
34,
112,
108,
97,
116,
102,
111,
114,
109,
34,
58,
34,
68,
69,
83,
75,
84,
79,
80,
34,
44,
34,
104,
108,
34,
58,
34,
101,
110,
45,
71,
66,
34,
44,
34,
103,
108,
34,
58,
34,
71,
66,
34,
44,
34,
117,
116,
99,
79,
102,
102,
115,
101,
116,
77,
105,
110,
117,
116,
101,
115,
34,
58,
48,
125,
44,
34,
114,
101,
113,
117,
101,
115,
116,
34,
58,
123,
34,
105,
110,
116,
101,
114,
110,
97,
108,
69,
120,
112,
101,
114,
105,
109,
101,
110,
116,
70,
108,
97,
103,
115,
34,
58,
91,
93,
44,
34,
117,
115,
101,
83,
115,
108,
34,
58,
116,
114,
117,
101,
125,
44,
34,
117,
115,
101,
114,
34,
58,
123,
34,
108,
111,
99,
107,
101,
100,
83,
97,
102,
101,
116,
121,
77,
111,
100,
101,
34,
58,
102,
97,
108,
115,
101,
125,
125,
125
],
"localization": {
"languageCode": "en",
"countryCode": "GB"
}
},
"response": {
"responseCode": 200,
"responseMessage": "",
"responseHeaders": {
"alt-svc": [
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000"
],
"content-type": [
"application/json; charset\u003dUTF-8"
],
"date": [
"Fri, 31 Oct 2025 18:29:14 GMT"
],
"server": [
"scaffolding on HTTPServer2"
],
"vary": [
"Origin",
"X-Origin",
"Referer"
],
"x-content-type-options": [
"nosniff"
],
"x-frame-options": [
"SAMEORIGIN"
],
"x-xss-protection": [
"0"
]
},
"responseBody": "{\"responseContext\":{\"visitorData\":\"Cgs2SUhNMHlFODI0OCj6_5PIBjIKCgJERRIEEgAgYg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20251030.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"GetVisitorId_rid\",\"value\":\"0xec3895f6276c55e0\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"visitor_data\",\"value\":\"Cgs2SUhNMHlFODI0OCj6_5PIBjIKCgJERRIEEgAgYg%3D%3D\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20251030\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}}}",
"latestUrl": "https://www.youtube.com/youtubei/v1/visitor_id?prettyPrint\u003dfalse"
}
}

View File

@@ -0,0 +1,369 @@
{
"request": {
"httpMethod": "POST",
"url": "https://youtubei.googleapis.com/youtubei/v1/visitor_id?prettyPrint\u003dfalse",
"headers": {
"User-Agent": [
"com.google.android.youtube/19.28.35 (Linux; U; Android 15; GB) gzip"
],
"X-Goog-Api-Format-Version": [
"2"
],
"Content-Type": [
"application/json"
],
"Accept-Language": [
"en-GB, en;q\u003d0.9"
]
},
"dataToSend": [
123,
34,
99,
111,
110,
116,
101,
120,
116,
34,
58,
123,
34,
99,
108,
105,
101,
110,
116,
34,
58,
123,
34,
99,
108,
105,
101,
110,
116,
78,
97,
109,
101,
34,
58,
34,
65,
78,
68,
82,
79,
73,
68,
34,
44,
34,
99,
108,
105,
101,
110,
116,
86,
101,
114,
115,
105,
111,
110,
34,
58,
34,
49,
57,
46,
50,
56,
46,
51,
53,
34,
44,
34,
99,
108,
105,
101,
110,
116,
83,
99,
114,
101,
101,
110,
34,
58,
34,
87,
65,
84,
67,
72,
34,
44,
34,
112,
108,
97,
116,
102,
111,
114,
109,
34,
58,
34,
77,
79,
66,
73,
76,
69,
34,
44,
34,
111,
115,
78,
97,
109,
101,
34,
58,
34,
65,
110,
100,
114,
111,
105,
100,
34,
44,
34,
111,
115,
86,
101,
114,
115,
105,
111,
110,
34,
58,
34,
49,
53,
34,
44,
34,
97,
110,
100,
114,
111,
105,
100,
83,
100,
107,
86,
101,
114,
115,
105,
111,
110,
34,
58,
51,
53,
44,
34,
104,
108,
34,
58,
34,
101,
110,
45,
71,
66,
34,
44,
34,
103,
108,
34,
58,
34,
71,
66,
34,
44,
34,
117,
116,
99,
79,
102,
102,
115,
101,
116,
77,
105,
110,
117,
116,
101,
115,
34,
58,
48,
125,
44,
34,
114,
101,
113,
117,
101,
115,
116,
34,
58,
123,
34,
105,
110,
116,
101,
114,
110,
97,
108,
69,
120,
112,
101,
114,
105,
109,
101,
110,
116,
70,
108,
97,
103,
115,
34,
58,
91,
93,
44,
34,
117,
115,
101,
83,
115,
108,
34,
58,
116,
114,
117,
101,
125,
44,
34,
117,
115,
101,
114,
34,
58,
123,
34,
108,
111,
99,
107,
101,
100,
83,
97,
102,
101,
116,
121,
77,
111,
100,
101,
34,
58,
102,
97,
108,
115,
101,
125,
125,
125
],
"localization": {
"languageCode": "en",
"countryCode": "GB"
}
},
"response": {
"responseCode": 200,
"responseMessage": "",
"responseHeaders": {
"alt-svc": [
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000"
],
"content-type": [
"application/json; charset\u003dUTF-8"
],
"date": [
"Fri, 31 Oct 2025 18:29:15 GMT"
],
"server": [
"scaffolding on HTTPServer2"
],
"vary": [
"Origin",
"X-Origin",
"Referer"
],
"x-content-type-options": [
"nosniff"
],
"x-frame-options": [
"SAMEORIGIN"
],
"x-xss-protection": [
"0"
]
},
"responseBody": "{\"responseContext\":{\"visitorData\":\"Cgtjd19UU1BJaGptVSj7_5PIBjIKCgJERRIEEgAgJDoMCAEg7uvHn7b_v4JpWL6Vu52txaLYiQE%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"ANDROID\"},{\"key\":\"cver\",\"value\":\"19.28.35\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"GetVisitorId_rid\",\"value\":\"0x44c86869ce39b885\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"visitor_data\",\"value\":\"Cgtjd19UU1BJaGptVSj7_5PIBjIKCgJERRIEEgAgJDoMCAEg7uvHn7b_v4Jp\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"19.28\"},{\"key\":\"client.name\",\"value\":\"ANDROID\"}]},{\"service\":\"LISTNR\",\"params\":[{\"key\":\"e\",\"value\":\"51534669,51493576\"}]}]}}",
"latestUrl": "https://youtubei.googleapis.com/youtubei/v1/visitor_id?prettyPrint\u003dfalse"
}
}