YouTube scraping is fragile -- page layouts change, rate limits kick in, and browser automation is slow. SERP APIs return YouTube video data as structured results when you search with site:youtube.com. You get video titles, channel names, view counts, and upload dates without Selenium, Playwright, or YouTube Data API quotas. Each search costs $0.005 and returns up to 10 video results.
Prerequisites
- Python 3.9+ or Node.js 18+
- requests library installed
- A Scavio API key from scavio.dev
Walkthrough
Step 1: Search YouTube via SERP API
Use site:youtube.com in your search query to get YouTube-only results. The SERP API returns structured data including video titles and channel info.
import requests, os
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
def search_youtube(query: str, count: int = 10) -> list:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': f'site:youtube.com {query}',
'country_code': 'us', 'num_results': count})
resp.raise_for_status()
results = resp.json().get('organic_results', [])
videos = []
for r in results:
link = r.get('link', '')
if 'youtube.com/watch' in link or 'youtu.be/' in link:
videos.append({
'title': r['title'].replace(' - YouTube', '').strip(),
'url': link,
'snippet': r.get('snippet', ''),
'channel': extract_channel(r.get('snippet', '')),
})
return videos
def extract_channel(snippet: str) -> str:
# YouTube snippets often start with channel name or duration
parts = snippet.split('\n') if '\n' in snippet else snippet.split(' ... ')
return parts[0].strip() if parts else ''
videos = search_youtube('python tutorial 2026')
for v in videos[:5]:
print(f'{v["title"][:50]}: {v["channel"][:30]}')
print(f'Cost: $0.005 for {len(videos)} videos')Step 2: Build a video research pipeline
Search multiple topics and aggregate video data for competitive analysis, content research, or influencer discovery.
import time
def research_videos(topics: list) -> dict:
all_videos = {}
for topic in topics:
videos = search_youtube(topic, count=10)
all_videos[topic] = videos
time.sleep(0.3)
# Aggregate stats
total_videos = sum(len(v) for v in all_videos.values())
channels = set()
for videos in all_videos.values():
for v in videos:
if v['channel']:
channels.add(v['channel'])
print(f'Topics: {len(topics)}')
print(f'Total videos found: {total_videos}')
print(f'Unique channels: {len(channels)}')
print(f'Cost: {len(topics)} queries = ${len(topics) * 0.005:.3f}')
return all_videos
topics = ['python api tutorial', 'javascript tutorial 2026', 'react hooks explained']
data = research_videos(topics)
for topic, videos in data.items():
print(f'\n{topic}: {len(videos)} videos')
for v in videos[:2]:
print(f' {v["title"][:50]}')Step 3: Compare with YouTube Data API approach
Show the difference between SERP API and YouTube Data API in terms of setup, quotas, and cost.
comparison = {
'SERP API (Scavio)': {
'setup': 'One API key, one POST call',
'quota': 'No daily quota, pay per query',
'cost': '$0.005/query (250 free/month)',
'data': 'Title, URL, snippet, channel name',
'rate_limit': '10 req/sec',
'auth': 'API key in header',
},
'YouTube Data API v3': {
'setup': 'Google Cloud project, OAuth consent, API enable',
'quota': '10,000 units/day (search = 100 units = 100 searches/day)',
'cost': 'Free up to quota, then blocked',
'data': 'Full metadata, stats, thumbnails',
'rate_limit': 'Quota-based',
'auth': 'OAuth2 or API key + project',
},
'Scraping (Selenium)': {
'setup': 'Browser driver, anti-detection, proxy',
'quota': 'IP-based blocks, unpredictable',
'cost': '$50-200/month for proxy + compute',
'data': 'Anything visible on page',
'rate_limit': '1-2 req/sec safely',
'auth': 'None (but proxies needed)',
},
}
for method, details in comparison.items():
print(f'{method}:')
for key, val in details.items():
print(f' {key}: {val}')
print()Python Example
import requests, os
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
def youtube_search(query, count=10):
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': f'site:youtube.com {query}', 'country_code': 'us', 'num_results': count})
return [{'title': r['title'].replace(' - YouTube', ''), 'url': r['link']}
for r in resp.json().get('organic_results', [])
if 'youtube.com/watch' in r.get('link', '')]
videos = youtube_search('python tutorial 2026')
for v in videos[:5]:
print(f'{v["title"][:50]}: {v["url"]}')JavaScript Example
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
async function youtubeSearch(query, count = 10) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: `site:youtube.com ${query}`, country_code: 'us', num_results: count })
});
const data = await resp.json();
return (data.organic_results || []).filter(r => r.link?.includes('youtube.com/watch'))
.map(r => ({ title: r.title.replace(' - YouTube', ''), url: r.link }));
}
youtubeSearch('python tutorial 2026').then(v => v.forEach(x => console.log(x.title)));Expected Output
Python Tutorial for Beginners 2026 - Full Course: Corey Schafer
Learn Python in 1 Hour - 2026 Edition: Programming with Mosh
Python API Tutorial - Build Your First API: Tech With Tim
Cost: $0.005 for 8 videos
SERP API (Scavio):
setup: One API key, one POST call
quota: No daily quota, pay per query
cost: $0.005/query (250 free/month)