Build a YouTube Channel Audit Tool with Playlists, Shorts, and Live Data
TL;DR: A proper YouTube channel audit goes beyond subscriber count and average views. By combining the channel info, playlists, shorts, and lives endpoints, you can build a script that evaluates content strategy depth, format diversification, and streaming activity — all in under 5 API credits per channel. This post walks through a complete Python implementation.
Jake works at a talent management agency. Every week, he reviews 15-20 YouTube channels — creators pitching for representation, or channels the team is considering for brand deals. His old process? Open each channel in a browser, click through tabs manually, eyeball the numbers, and type notes into a spreadsheet.
It took him about 20 minutes per channel. That's 5-6 hours per week of clicking around YouTube, squinting at view counts, and trying to remember whether the channel had playlists organized well or if their shorts were getting traction.
The audit tool he built with four API calls per channel now does that initial assessment in about 3 seconds. He still makes the final judgment call — but the data gathering isn't a time sink anymore.
What a Comprehensive Channel Audit Covers
A surface-level audit looks at subscribers and recent video views. A proper audit evaluates:
| Dimension | What It Tells You | Endpoint |
|---|---|---|
| Channel fundamentals | Scale, growth indicators, branding | channel |
| Content organization | Strategic thinking, series development | channel/playlists |
| Short-form presence | Format diversification, discovery potential | channel/shorts |
| Live streaming activity | Community engagement, real-time connection | channel/lives |
| Video catalog depth | Consistency, output volume | channel-videos |
A creator who has 500K subscribers but no playlists, no shorts, and has never gone live is a very different investment than one with the same subscriber count who runs a structured content series, posts shorts 3x/week, and streams monthly Q&As.
The Complete Audit Script
Here's a Python script that pulls data from multiple endpoints and generates a structured audit report:
import requests
import json
from datetime import datetime
API_KEY = "your_sociavault_api_key"
BASE_URL = "https://api.sociavault.com/v1/scrape/youtube"
HEADERS = {"X-API-Key": API_KEY}
def fetch_endpoint(path, params):
"""Generic fetch helper with error handling."""
response = requests.get(
f"{BASE_URL}/{path}",
params=params,
headers=HEADERS
)
if response.status_code == 200:
data = response.json()
if data.get("success"):
return data.get("data", {})
return None
def audit_channel(handle):
"""Run a comprehensive audit on a YouTube channel."""
print(f"\n{'='*60}")
print(f"CHANNEL AUDIT: @{handle}")
print(f"{'='*60}")
print(f"Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
audit = {
"handle": handle,
"timestamp": datetime.now().isoformat(),
"sections": {}
}
# 1. Channel fundamentals (1 credit)
print("Fetching channel info...")
channel = fetch_endpoint("channel", {"handle": handle})
if not channel:
print(f"ERROR: Could not fetch channel data for @{handle}")
return None
audit["sections"]["fundamentals"] = {
"name": channel.get("name"),
"subscribers": channel.get("subscriberCount", 0),
"total_views": channel.get("viewCount", 0),
"video_count": channel.get("videoCount", 0),
"joined": channel.get("joinedDateText", "Unknown"),
"country": channel.get("country", "Unknown"),
"has_email": bool(channel.get("email")),
"external_links": len(channel.get("links", {})),
}
subs = channel.get("subscriberCount", 0)
views = channel.get("viewCount", 0)
videos = channel.get("videoCount", 0)
avg_views_per_video = views // videos if videos > 0 else 0
views_per_sub = round(views / subs, 1) if subs > 0 else 0
print(f" Subscribers: {subs:,}")
print(f" Total views: {views:,}")
print(f" Videos: {videos}")
print(f" Avg views/video: {avg_views_per_video:,}")
print(f" Lifetime views/subscriber: {views_per_sub}")
# 2. Playlists — content organization (1 credit)
print("\nFetching playlists...")
playlists_data = fetch_endpoint("channel/playlists", {"handle": handle})
playlists = []
if playlists_data:
playlists = playlists_data.get("playlists", [])
audit["sections"]["playlists"] = {
"total_playlists": len(playlists),
"playlist_titles": [p.get("title", "") for p in playlists[:10]],
}
print(f" Total playlists: {len(playlists)}")
if playlists:
print(f" Top playlists:")
for p in playlists[:5]:
title = p.get("title", "Untitled")
count = p.get("videoCount", "?")
print(f" - {title} ({count} videos)")
# 3. Shorts presence (1 credit)
print("\nFetching shorts...")
shorts_data = fetch_endpoint("channel/shorts", {"handle": handle})
shorts = []
if shorts_data:
shorts = shorts_data.get("shorts", [])
audit["sections"]["shorts"] = {
"has_shorts": len(shorts) > 0,
"recent_shorts_count": len(shorts),
"sample_titles": [s.get("title", "") for s in shorts[:5]],
}
print(f" Has shorts: {'Yes' if shorts else 'No'}")
print(f" Recent shorts found: {len(shorts)}")
if shorts:
# Analyze shorts view counts
shorts_views = []
for s in shorts:
view_text = s.get("viewCountText", "0")
print(f" - {s.get('title', 'Untitled')[:50]} | {view_text}")
# 4. Live streaming activity (1 credit)
print("\nFetching live streams...")
lives_data = fetch_endpoint("channel/lives", {"handle": handle})
lives = []
if lives_data:
lives = lives_data.get("lives", [])
audit["sections"]["lives"] = {
"has_streamed": len(lives) > 0,
"recent_streams_count": len(lives),
"sample_titles": [l.get("title", "") for l in lives[:5]],
}
print(f" Has live streams: {'Yes' if lives else 'No'}")
print(f" Recent streams found: {len(lives)}")
if lives:
for l in lives[:3]:
title = l.get("title", "Untitled")[:50]
views = l.get("viewCountText", "N/A")
print(f" - {title} | {views}")
# Generate audit score
score = calculate_audit_score(audit)
audit["score"] = score
print(f"\n{'='*60}")
print(f"AUDIT SCORE: {score['total']}/100")
print(f"{'='*60}")
print(f" Fundamentals: {score['fundamentals']}/30")
print(f" Organization: {score['organization']}/25")
print(f" Diversification: {score['diversification']}/25")
print(f" Engagement signals: {score['engagement']}/20")
return audit
def calculate_audit_score(audit):
"""Score a channel based on audit data."""
score = {
"fundamentals": 0,
"organization": 0,
"diversification": 0,
"engagement": 0,
}
sections = audit["sections"]
# Fundamentals (max 30)
fund = sections["fundamentals"]
subs = fund["subscribers"]
if subs >= 1_000_000:
score["fundamentals"] += 15
elif subs >= 100_000:
score["fundamentals"] += 12
elif subs >= 10_000:
score["fundamentals"] += 8
elif subs >= 1_000:
score["fundamentals"] += 4
if fund["has_email"]:
score["fundamentals"] += 5
if fund["external_links"] >= 2:
score["fundamentals"] += 5
if fund["country"] != "Unknown":
score["fundamentals"] += 5
# Organization (max 25)
playlists = sections["playlists"]
playlist_count = playlists["total_playlists"]
if playlist_count >= 10:
score["organization"] += 25
elif playlist_count >= 5:
score["organization"] += 20
elif playlist_count >= 3:
score["organization"] += 15
elif playlist_count >= 1:
score["organization"] += 8
# Diversification (max 25)
has_shorts = sections["shorts"]["has_shorts"]
has_lives = sections["lives"]["has_streamed"]
if has_shorts:
score["diversification"] += 12
if has_lives:
score["diversification"] += 13
# Engagement signals (max 20)
if subs > 0:
avg_views = fund["total_views"] / max(fund.get("video_count", 1), 1)
view_sub_ratio = avg_views / subs
if view_sub_ratio >= 0.3:
score["engagement"] += 20
elif view_sub_ratio >= 0.15:
score["engagement"] += 15
elif view_sub_ratio >= 0.05:
score["engagement"] += 10
else:
score["engagement"] += 5
score["total"] = sum(score.values())
return score
# Run the audit
if __name__ == "__main__":
channels_to_audit = ["MrBeast", "MarcusHouse", "LexFridman"]
results = []
for handle in channels_to_audit:
result = audit_channel(handle)
if result:
results.append(result)
# Save full results to JSON
with open("audit_results.json", "w") as f:
json.dump(results, f, indent=2)
print(f"\n\nAudit complete. {len(results)} channels analyzed.")
print(f"Total credits used: ~{len(results) * 4}")
This script uses 4 credits per channel (channel info + playlists + shorts + lives). For Jake's weekly batch of 20 channels, that's 80 credits.
Understanding the Audit Score
The scoring framework weighs four dimensions:
Fundamentals (30 points)
Raw metrics: subscriber count, whether they have a contact email listed, external links (indicating business readiness), and geographic info. A channel that's clearly set up for business scores higher here.
Organization (25 points)
Playlist count and structure. Channels with well-organized playlists signal strategic content thinking. A creator with 10+ themed playlists is running a content library, not just uploading randomly.
Diversification (25 points)
Are they using multiple formats? Shorts + long-form + live = maximum reach potential. A channel using only long-form video is leaving discovery opportunities on the table.
Engagement Signals (20 points)
Average views relative to subscriber count. A 100K-subscriber channel averaging 30K views per video (30% ratio) is healthier than a 1M-subscriber channel averaging 50K views (5% ratio).
Interpreting Results
| Score Range | Assessment | Recommendation |
|---|---|---|
| 80-100 | Excellent | Strong partnership candidate |
| 60-79 | Good | Worth deeper analysis |
| 40-59 | Developing | Potential, but higher risk |
| Below 40 | Concerns | Investigate further before committing |
Important caveat: A score isn't a verdict. A niche educational channel might score 55 because they don't stream and have few playlists — but they could still be an excellent sponsorship fit for the right brand. The score identifies where to dig deeper, not whether to sign or pass.
Extending the Audit
Add Video Performance Analysis
Pull recent videos to calculate actual engagement rates:
def get_recent_video_performance(handle, video_count=30):
"""Pull recent videos and calculate engagement metrics."""
videos_data = fetch_endpoint("channel-videos", {
"handle": handle,
"sort": "latest"
})
if not videos_data:
return None
videos = videos_data.get("videos", [])[:video_count]
view_counts = []
for v in videos:
view_text = v.get("viewCountText", "0 views")
# Parse view count from text (simplified)
view_counts.append(v.get("viewCount", 0))
if not view_counts:
return None
return {
"videos_analyzed": len(view_counts),
"avg_views": sum(view_counts) // len(view_counts),
"max_views": max(view_counts),
"min_views": min(view_counts),
"median_views": sorted(view_counts)[len(view_counts) // 2],
}
Add Community Engagement Check
Layer in community post data to assess subscriber loyalty:
def check_community_engagement(handle, subscriber_count):
"""Check community post engagement relative to subscriber count."""
posts_data = fetch_endpoint("channel/community-posts", {"handle": handle})
if not posts_data:
return {"active": False}
posts = posts_data.get("posts", [])
if not posts:
return {"active": False}
like_counts = [p.get("likeCount", 0) for p in posts[:10]]
avg_likes = sum(like_counts) // len(like_counts) if like_counts else 0
engagement_rate = (avg_likes / subscriber_count * 100) if subscriber_count > 0 else 0
return {
"active": True,
"posts_found": len(posts),
"avg_likes": avg_likes,
"community_engagement_rate": round(engagement_rate, 2),
}
Batch Processing with CSV Output
For agencies processing many channels at once:
import csv
def batch_audit_to_csv(handles, output_file="channel_audits.csv"):
"""Audit multiple channels and export to CSV."""
fieldnames = [
"handle", "name", "subscribers", "total_views",
"video_count", "playlist_count", "has_shorts",
"has_lives", "audit_score", "timestamp"
]
with open(output_file, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
for handle in handles:
result = audit_channel(handle)
if result:
sections = result["sections"]
writer.writerow({
"handle": handle,
"name": sections["fundamentals"]["name"],
"subscribers": sections["fundamentals"]["subscribers"],
"total_views": sections["fundamentals"]["total_views"],
"video_count": sections["fundamentals"].get("video_count", 0),
"playlist_count": sections["playlists"]["total_playlists"],
"has_shorts": sections["shorts"]["has_shorts"],
"has_lives": sections["lives"]["has_streamed"],
"audit_score": result["score"]["total"],
"timestamp": result["timestamp"],
})
print(f"\nExported {len(handles)} audits to {output_file}")
Real-World Scoring Examples
To calibrate expectations, here's how different channel archetypes typically score:
Full-time creator (gaming/entertainment): 75-90. Active across all formats, playlists for series, regular streams, shorts for clips.
Educational channel: 50-70. Strong fundamentals and organization (playlists), but often no shorts or lives. Their engagement ratio is usually excellent.
Corporate brand channel: 40-60. Few playlists, no lives, limited shorts. But fundamentals (subscriber count, branding) might be solid.
New but fast-growing creator: 35-55. Low subscriber count hurts fundamentals score, but diversification and engagement might be high.
Frequently Asked Questions
How many credits does a full audit use?
4 credits per channel for the basic audit (channel + playlists + shorts + lives). Add 1-2 more if you include community posts and video performance checks.
Can I audit channels I don't own?
Yes. All endpoints use publicly available data — the same information anyone can see by visiting the channel in a browser.
How often should I re-audit a channel?
For active partnership evaluations, once before signing. For ongoing portfolio monitoring, monthly is sufficient. Channel fundamentals don't change dramatically day-to-day.
What about channels with content in non-English languages?
The API returns data regardless of language. Titles and descriptions come through in the original language. The scoring framework works across languages since it's metric-based.
Can I compare channels in different niches fairly?
The score provides a within-channel assessment of how well they're using YouTube's features. Cross-niche comparison is tricky — a 60-score cooking channel and a 60-score gaming channel have different profiles. Use the score for same-niche comparison or as an absolute quality signal.
Is there a way to track audit scores over time?
The script outputs JSON — store it with timestamps and you've got a longitudinal record. Plot scores over months to see if a creator is investing in their channel or stagnating.
What This Doesn't Tell You
An audit tool flags strengths and gaps in channel infrastructure. It doesn't measure:
- Content quality (watch the videos)
- Brand safety (review recent content manually)
- Audience demographics (not available via public data)
- Revenue or monetization status
Use the audit as a first-pass filter to decide which channels deserve deeper human review — not as the final decision-maker.
Try SociaVault free → — 50 free credits, enough to audit 12 channels end-to-end. No card required.
Related reading:
- YouTube Channel Scraper API — Channel data endpoint details
- YouTube Live Stream Tracker — Deep dive on the lives endpoint
- Creator Due Diligence Checklist — Full vetting framework
- Influencer Vetting: Detect Fake Followers — Authenticity checks
Found this helpful?
Share it with others who might benefit
Ready to Try SociaVault?
Start extracting social media data with our powerful API. No credit card required.