You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过YouTube Data API批量添加订阅页未看视频至稍后观看

Hey there! Let's break down how to get this working—whether you want a quick browser script (no API hoops) or the proper YouTube Data API implementation you're trying to use. I’ve messed around with similar scripts for YouTube, so here’s what you need to know.

Quick Browser Script (No API Required)

If you just need a temporary solution to run directly in your browser’s console on the subscriptions page, this is the fastest way. It simulates clicking the "Save to Watch Later" option for every unwatched video:

First, we’ll scroll to load all lazy-loaded videos, then batch process them:

// Scroll to load all unwatched videos (adjust timeouts if needed for slow internet)
function scrollToLoadAll() {
  return new Promise((resolve) => {
    const scrollInterval = setInterval(() => {
      window.scrollTo(0, document.body.scrollHeight);
      const lastHeight = document.body.scrollHeight;
      setTimeout(() => {
        if (document.body.scrollHeight === lastHeight) {
          clearInterval(scrollInterval);
          resolve();
        }
      }, 1000);
    }, 1500);
  });
}

// Batch add unwatched videos to Watch Later
async function batchAddToWatchLater() {
  await scrollToLoadAll();
  
  // Grab all unwatched videos (marked by the absence of the "is-watched" attribute)
  const unWatchedVideos = document.querySelectorAll('ytd-grid-video-renderer:not([is-watched])');
  
  console.log(`Found ${unWatchedVideos.length} unwatched videos to process`);
  
  for (const video of unWatchedVideos) {
    try {
      // Open the "More actions" menu
      const moreBtn = video.querySelector('#button[aria-label="More actions"]');
      if (!moreBtn) continue;
      moreBtn.click();
      
      // Wait for the menu to render
      await new Promise(resolve => setTimeout(resolve, 500));
      
      // Click "Save to Watch Later"
      const watchLaterOption = document.querySelector('yt-formatted-string[aria-label="Save to Watch Later"]');
      if (watchLaterOption) {
        watchLaterOption.click();
        console.log(`Added: ${video.querySelector('#video-title').innerText}`);
      }
      
      // Close the menu before moving to the next video
      await new Promise(resolve => setTimeout(resolve, 300));
      document.body.click();
    } catch (err) {
      console.error(`Skipping video due to error:`, err);
    }
  }
  
  console.log('Batch add complete! 🎉');
}

// Run the script
batchAddToWatchLater();

Notes for this method:

  • YouTube updates its DOM structure occasionally, so if selectors break, inspect the page to find new ones.
  • Don’t run this too frequently—YouTube might flag your actions as automated and temporarily restrict access.
  • Adjust the timeout values if you have slow internet (give more time for videos to load and menus to open).

Using the YouTube Data API (Insert Method)

If you want a more robust solution (and are running into issues with the API), let’s fix those common pain points. The main hurdles are authentication, finding the Watch Later playlist ID, and avoiding quota limits.

Step 1: Set Up API Access

First, you’ll need to:

  • Go to the Google Cloud Console, create a project, and enable the YouTube Data API v3.
  • Create OAuth 2.0 credentials (since you’re modifying user-specific data).
  • Make sure your OAuth scope includes https://www.googleapis.com/auth/youtube (or youtube.force-ssl for read/write access).

Step 2: Working Code Implementation

This script will authenticate the user, fetch their Watch Later playlist ID, then batch add unwatched videos via the API:

// Reuse the scroll function from the previous script to load all videos
function scrollToLoadAll() {
  return new Promise((resolve) => {
    const scrollInterval = setInterval(() => {
      window.scrollTo(0, document.body.scrollHeight);
      const lastHeight = document.body.scrollHeight;
      setTimeout(() => {
        if (document.body.scrollHeight === lastHeight) {
          clearInterval(scrollInterval);
          resolve();
        }
      }, 1000);
    }, 1500);
  });
}

// Fetch the user's Watch Later playlist ID
async function getWatchLaterId(accessToken) {
  const res = await fetch('https://www.googleapis.com/youtube/v3/channels?part=contentDetails&mine=true', {
    headers: { 'Authorization': `Bearer ${accessToken}` }
  });
  const data = await res.json();
  return data.items[0].contentDetails.relatedPlaylists.watchLater;
}

// Add a single video to Watch Later via API
async function addVideoToPlaylist(accessToken, playlistId, videoId) {
  const res = await fetch('https://www.googleapis.com/youtube/v3/playlistItems', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      snippet: {
        playlistId: playlistId,
        resourceId: { kind: 'youtube#video', videoId: videoId }
      }
    })
  });
  return res.json();
}

// Batch process videos using the API
async function batchAddViaAPI() {
  // Handle OAuth authentication (use Google's gapi library for browser-based auth)
  // Example auth flow:
  // await gapi.auth2.getAuthInstance().signIn();
  // const accessToken = gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().access_token;
  
  // Replace with your actual access token after auth
  const accessToken = 'YOUR_VALID_ACCESS_TOKEN';
  const watchLaterId = await getWatchLaterId(accessToken);
  
  // Load all videos and get their IDs
  await scrollToLoadAll();
  const unWatchedVideos = document.querySelectorAll('ytd-grid-video-renderer:not([is-watched])');
  const videoIds = Array.from(unWatchedVideos).map(video => {
    const url = video.querySelector('#video-title').href;
    return new URL(url).searchParams.get('v');
  });
  
  console.log(`Processing ${videoIds.length} videos via API`);
  
  // Batch insert with delays to avoid quota/rate limits
  for (const id of videoIds) {
    try {
      await addVideoToPlaylist(accessToken, watchLaterId, id);
      console.log(`Added video ID: ${id}`);
      // Add a 1-second delay to stay under rate limits
      await new Promise(resolve => setTimeout(resolve, 1000));
    } catch (err) {
      console.error(`Failed to add ${id}:`, err);
    }
  }
  
  console.log('API batch operation complete!');
}

// Run after setting up auth
// batchAddViaAPI();

Common API Issues & Fixes

  • Authorization Errors: Double-check your OAuth scope—you need write access to modify playlists. Also, ensure the user has granted permission to your app.
  • Quota Limits: The YouTube API uses a quota system (10,000 units/day by default). Each playlistItems.insert call uses 50 units, so you can add ~200 videos/day. If you need more, request a quota increase in the Google Cloud Console.
  • CORS Errors: If running from the browser console, direct fetch calls might hit CORS issues. Use Google’s official gapi library instead, or wrap the script in a browser extension (which bypasses CORS restrictions).
  • Duplicate Videos: The API will throw an error if the video is already in Watch Later. To avoid this, you can pre-check with a playlistItems.list call (but this uses additional quota).

内容的提问来源于stack exchange,提问作者Denis Davydenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:00:49