YouTube Video Metadata API: A Python Workflow for Structured Creator Research
A useful creator-research workflow starts with a stable record format, not a spreadsheet of copied links. If your team needs to review public YouTube videos across a defined set of channels or topics, model every result as structured metadata: the source URL, title, publication time when available, observed metrics, collection timestamp, and a clear provenance note. That gives researchers a dataset they can validate, enrich, and re-run without losing track of where each value came from.
This guide is for developers and research teams who want to turn public video results into a reviewable JSON workflow. It uses the repository examples in the data-scrape GitHub organization, especially the YouTube Video Scraper API project and the related YouTube Channel Scraper. The repositories provide implementation references; they are not a guarantee of a production data service, complete field coverage, or a fixed endpoint contract.
Quick answer
For structured creator research:
- Define the video fields you need before collecting anything.
- Store every public result with its source URL and collection time.
- Normalize missing values rather than inventing defaults.
- Keep extraction, transformation, and analyst review as separate steps.
- Use a repository-based scraper only after validating its README, code, current maintenance status, and target-platform requirements.
The key outcome is a dataset that can answer a specific question, such as: Which topics appeared in a competitor channel's latest public videos? Which videos should an analyst review manually? Which records are too incomplete to use?
Why a JSON workflow beats ad-hoc exports
A CSV is fine for a one-off review. It becomes fragile when records arrive over several runs, values change, or different people need to understand how a number was collected. JSON keeps related fields together and makes provenance explicit.
A minimal public-video record can look like this:
{
"video_url": "https://www.youtube.com/watch?v=example",
"channel_url": "https://www.youtube.com/@example",
"title": "Example public video title",
"published_at": null,
"observed_views": null,
"collected_at": "2026-08-12T02:00:00Z",
"source": "public YouTube page",
"review_status": "needs_review"
}
This shape makes uncertainty visible. null means the field was unavailable or not yet verified; it does not mean zero. collected_at separates the time you observed a value from the video publication date. review_status keeps the data pipeline from quietly turning raw web output into a business conclusion.
Start with an explicit research question
Do not begin by collecting every field that a tool might expose. Start with a question and only keep data needed to answer it.
| Research question | Minimum useful fields | Human validation needed? |
|---|---|---|
| Find recent videos about a product category | title, video URL, channel URL, observed publication time | Yes, for topical relevance |
| Create a manual creator-review queue | title, channel name, video URL, collection time | Yes, before outreach or decisions |
| Compare publishing cadence | channel URL, public video URL, observed publication time, collection time | Yes, for edge cases and deleted content |
| Build a content taxonomy | title, description when public, URL, reviewer label | Yes, for category accuracy |
This constraint is useful for engineering too. It reduces work, limits retention of unnecessary data, and makes a failed or partial extraction easier to diagnose.
Repository roles: channel discovery and video records
The YouTube Channel Scraper repository documents a Python-based project for extracting publicly available channel information and video URLs. Its README shows Python and command-line examples, and describes JSON, CSV, and Excel output options.
The YouTube Video Scraper API repository documents a separate project focused on video-data extraction, with JSON responses, pagination, Docker deployment, Swagger documentation, rate limiting, and batch-video lookup listed in its README. Verify the source code and current documentation before adopting any request format, deployment behavior, or response field in production: a repository README is an implementation reference, not a service-level agreement.
A sensible separation is:
- Channel stage: produce a candidate list of public channel or video URLs.
- Video stage: collect and normalize video-level records for those URLs.
- Research stage: classify and review the records using explicit rules.
That separation lets you replace one component when page structures, dependencies, or target-site requirements change.
Install and inspect before integrating
The channel repository documents installation from GitHub for Python 3.8+:
pip install git+https://github.com/data-scrape/youtube-channel-scraper.git
The video project documents a similar repository installation pattern:
pip install git+https://github.com/data-scrape/youtube-video-scraper-api.git
Before wiring either into an automated job, review four things:
- The latest README and dependency list.
- Open issues and recent commits for maintenance signals.
- The exact returned fields in a controlled test run.
- Your legal, privacy, and target-platform obligations for the intended collection.
Avoid treating an example import, a repository name, or an illustrative scrape("your-query") call as proof that every query format, field, or output is supported in your environment.
Normalize raw results with a small Python transformer
The following code does not call a scraper or claim any live-data endpoint. It demonstrates the safer middle stage: transforming representative public-video records into a consistent JSON schema that your team can review.
import json
import os
from datetime import datetime, timezone
from pathlib import Path
INPUT_FILE = Path(os.environ.get("VIDEO_INPUT", "raw_videos.json"))
OUTPUT_FILE = Path(os.environ.get("VIDEO_OUTPUT", "normalized_videos.json"))
def clean_text(value):
if not isinstance(value, str):
return None
value = " ".join(value.split())
return value or None
def as_non_negative_int(value):
if isinstance(value, bool):
return None
if isinstance(value, int) and value >= 0:
return value
if isinstance(value, str) and value.strip().isdigit():
return int(value.strip())
return None
def normalize_video(raw, collected_at):
url = clean_text(raw.get("video_url") or raw.get("url"))
if not url:
return None
return {
"video_url": url,
"channel_url": clean_text(raw.get("channel_url")),
"channel_name": clean_text(raw.get("channel_name")),
"title": clean_text(raw.get("title")),
"description": clean_text(raw.get("description")),
"published_at": clean_text(raw.get("published_at")),
"observed_views": as_non_negative_int(raw.get("view_count")),
"observed_likes": as_non_negative_int(raw.get("like_count")),
"collected_at": collected_at,
"source": "public web result",
"review_status": "needs_review",
}
raw_records = json.loads(INPUT_FILE.read_text(encoding="utf-8"))
if not isinstance(raw_records, list):
raise ValueError("Expected a JSON array of raw video records")
collected_at = datetime.now(timezone.utc).isoformat()
normalized = []
seen_urls = set()
for raw in raw_records:
if not isinstance(raw, dict):
continue
record = normalize_video(raw, collected_at)
if record and record["video_url"] not in seen_urls:
normalized.append(record)
seen_urls.add(record["video_url"])
OUTPUT_FILE.write_text(json.dumps(normalized, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"Saved {len(normalized)} normalized records to {OUTPUT_FILE}")
The transformer makes three practical decisions: it removes whitespace-only values, retains unknown fields as null, and removes exact duplicate URLs. It does not assume that a missing metric means a zero metric, or that a date string has already been validated.
Representative input and output
A raw record from any collection stage may use inconsistent field names or types:
[
{
"url": "https://www.youtube.com/watch?v=example",
"channel_name": "Example Creator",
"title": " Public video title ",
"view_count": "1200",
"like_count": 80
}
]
After normalization, the record becomes easier to work with downstream:
[
{
"video_url": "https://www.youtube.com/watch?v=example",
"channel_url": null,
"channel_name": "Example Creator",
"title": "Public video title",
"description": null,
"published_at": null,
"observed_views": 1200,
"observed_likes": 80,
"collected_at": "2026-08-12T02:00:00+00:00",
"source": "public web result",
"review_status": "needs_review"
}
]
At this point, a reviewer can validate relevance, mark invalid records, or add a taxonomy label. That is far safer than letting a raw title or estimated engagement number drive a sales, editorial, or marketing action automatically.
Build reliability checks into the workflow
Public web pages change. Fields may disappear, videos may be removed, pages may render differently by region, and a repository may need maintenance after a dependency update. Treat these as routine conditions, not exceptions.
Use a pre-run checklist:
- [ ] Confirm that the repository and its dependencies are still maintained enough for a test run.
- [ ] Test against a small, approved set of public URLs.
- [ ] Record collection time and source URL for each result.
- [ ] Keep missing fields as missing rather than substituting assumptions.
- [ ] Deduplicate by canonical video URL where possible.
- [ ] Add retries and error logs only after you know the tool's documented behavior.
- [ ] Have a human review high-impact records before publishing, outreach, or business decisions.
For recurring work, measure record completeness and error rates over time. A sudden jump in missing titles or URLs is often more meaningful than the raw number of collected rows.
Common use cases
Content research. Build a manual queue of public videos around a topic, then label them by format, audience, or product mention.
Creator-marketplace operations. Collect a reviewable set of public channel and video URLs, then ask a human operator to validate fit before contact or partnership decisions.
Media analysis. Preserve source URLs and collection times so a report can distinguish observed values from conclusions.
Developer prototyping. Use repository examples to test a JSON schema and transformation process before committing to a production data source.
None of these use cases should be read as permission to collect restricted information, ignore platform controls, or automate actions against people without a lawful basis.
Repository workflow versus a managed data provider
| Dimension | Repository-based workflow | Managed data provider |
|---|---|---|
| Control over schema | You define transformation and storage | Provider schema guides integration |
| Maintenance | Your team monitors code and page changes | Provider typically manages its service layer |
| Observability | You design logs, tests, and alerts | Varies by provider plan and product |
| Field certainty | Validate from actual test outputs | Validate from current provider documentation |
| Compliance review | Your responsibility | Still your responsibility; provider tooling does not replace it |
A repository can be an excellent learning or prototyping asset. Production adoption still needs authentication handling where required, error monitoring, data retention rules, access controls, and a documented basis for using each type of public information.
Limitations and compliance
Use only publicly available information in a way that respects applicable law, privacy requirements, and the target platform's terms. Do not try to evade login requirements, technical restrictions, rate limits, or access controls. Do not use public-profile information to infer sensitive traits or make consequential automated decisions.
Repository examples can change, and public page data is not automatically complete or correct. Verify the latest project documentation and test output before relying on a field, a supported format, an authentication pattern, or a claimed capability.
FAQ
Is a GitHub repository a production API?
No. A repository may contain examples, code, or deployment instructions. Review its code and documentation before deciding whether it fits a production system.
Why save collected_at when video pages have their own dates?
A page publication date and the time your workflow observed a value are different facts. Keeping both helps analysts understand freshness and changes over time.
Can I automatically treat missing views as zero?
No. A missing value may mean the field was unavailable, the parser changed, the source was incomplete, or the record needs manual review.
Should I retain every raw response?
Only retain what your research purpose, governance rules, and legal obligations justify. Keep enough provenance to audit a result without accumulating unnecessary data.
How often should a recurring collection run?
Choose a cadence based on the actual decision being supported, platform requirements, and the cost of reviewing changes. Test a small cadence first and adjust based on observed value.
Where can I inspect the referenced projects?
Start with the data-scrape profile, then review the YouTube Video Scraper API repository and YouTube Channel Scraper repository directly.
Next step
Before integrating a public-video workflow, write the target JSON schema, collect a controlled test sample, and assign someone to validate output quality. The repository examples above are useful starting points for that evaluation; the durable asset is the documented, reviewable workflow your team builds around them.
Top comments (0)