ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Fact-Check YouTube Videos With an API
Tutorial

How to Fact-Check YouTube Videos With an API

Pull a YouTube video's metadata, extract claims, and ground them against live Google results with the Scavio API. Working Python and JS.

Get Free API KeyAPI Docs

To fact-check a YouTube video with an API, pull the video's metadata with Scavio's YouTube metadata endpoint, extract candidate claims from the title and description with an LLM, then query Google for each claim and check whether reputable results support or contradict it. Scavio returns metadata, not a transcript, so the claim extraction runs on the text you have or on a transcript from your own source. The output is a per-claim verdict (supported, unsupported, or mixed) with source URLs. This flags claims for human review; it is not a truth oracle. The value here is grounding: instead of trusting one model's memory, you anchor every judgement to live Google results that a person can open and read.

Prerequisites

  • A Scavio API key (sk_live_...) from your dashboard; new accounts get 50 free credits.
  • Python 3.9+ with requests, or Node.js 18+ for the JavaScript version.
  • An LLM you can call for claim extraction and support judgement (Claude or similar).
  • A YouTube video URL or ID you want to check.

Walkthrough

Step 1: Fetch the video metadata

Send the video URL or ID to the YouTube metadata endpoint. You get back the title, description, channel, and stats such as views, likes, and comment counts. Note that this is metadata only; there is no transcript in the response. The description is the richest field here, since creators often pack it with specific claims, dates, and links you can check. Keep the raw stats too, because a claim that contradicts a video with millions of views is worth surfacing prominently.

Python
import requests

resp = requests.post(
    "https://api.scavio.dev/api/v1/youtube/metadata",
    headers={
        "Authorization": "Bearer sk_live_...",
        "Content-Type": "application/json",
    },
    json={"query": "https://www.youtube.com/watch?v=VIDEO_ID"},
)
data = resp.json()
print(data["title"], data["channel"], data["stats"]["views"])

Step 2: Extract candidate claims

Pass the title and description to an LLM and ask it for a short list of checkable factual statements. If you have a transcript from your own source, add it here for fuller coverage; the API will not give you one. Each claim should be one specific assertion you can search for, such as a number, a date, or a named cause and effect. Drop opinions and vague phrasing, because they cannot be grounded against search results. This is the step where the LLM does real work, and where you should review its output before trusting the rest of the pipeline.

Python
# Scavio returns metadata, not a transcript.
# An LLM turns the title + description into checkable claims.
metadata_text = f"{data['title']}\n\n{data['description']}"

claims = extract_claims_with_llm(metadata_text)
# -> ["The battery lasts 40 hours", "It ships in March 2026", ...]
for c in claims:
    print("CLAIM:", c)

Step 3: Ground each claim in Google results

For every claim, query the Google endpoint with light_request set to false so you get organic results, the knowledge graph, and news results. This costs 2 credits per query at that setting; the default light_request of true costs 1 credit but returns less. Phrase the query as the claim itself, or as the claim turned into a neutral question, so you do not bias the results toward agreement. Reading both organic results and news lets you catch claims that were true once but have since been corrected.

Python
import requests

def ground_claim(claim):
    resp = requests.post(
        "https://api.scavio.dev/api/v1/google",
        headers={
            "Authorization": "Bearer sk_live_...",
            "Content-Type": "application/json",
        },
        json={"query": claim, "light_request": False},
    )
    g = resp.json()
    return g["organic"], g.get("knowledge_graph"), g.get("news_results")

Step 4: Score the claim and attach sources

Feed the top results back to the LLM and ask it to judge whether they support, contradict, or partially match the claim. Record the verdict, a confidence value, and the source URLs so a human can verify the call. Be conservative: when the results are thin or conflicting, label the claim mixed rather than forcing a yes or no. The confidence score and the attached links are what make this output reviewable, which matters because the model judging support can still be wrong.

Python
def score_claim(claim, organic):
    # Feed the top results back to the LLM to judge support.
    sources = [{"title": r["title"], "url": r["link"], "snippet": r["snippet"]}
               for r in organic[:5]]
    verdict = judge_with_llm(claim, sources)  # supported | unsupported | mixed
    return {
        "claim": claim,
        "verdict": verdict["label"],
        "confidence": verdict["confidence"],
        "sources": [s["url"] for s in sources],
    }

Python Example

Python
import requests

API_KEY = "sk_live_..."
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}
BASE = "https://api.scavio.dev/api/v1"


def get_metadata(video_url):
    resp = requests.post(
        f"{BASE}/youtube/metadata",
        headers=HEADERS,
        json={"query": video_url},
    )
    resp.raise_for_status()
    return resp.json()


def ground_claim(claim):
    resp = requests.post(
        f"{BASE}/google",
        headers=HEADERS,
        json={"query": claim, "light_request": False},
    )
    resp.raise_for_status()
    return resp.json()


def extract_claims_with_llm(text):
    # Replace with a real LLM call (Claude, etc.).
    # Return a list of short, checkable factual statements.
    raise NotImplementedError


def judge_with_llm(claim, sources):
    # Replace with a real LLM call.
    # Return {"label": "supported|unsupported|mixed", "confidence": 0.0-1.0}
    raise NotImplementedError


def fact_check(video_url):
    meta = get_metadata(video_url)
    print(f"Video: {meta['title']} ({meta['stats']['views']} views)")

    text = f"{meta['title']}\n\n{meta['description']}"
    claims = extract_claims_with_llm(text)

    report = []
    for claim in claims:
        g = ground_claim(claim)
        organic = g.get("organic", [])
        sources = [{"title": r["title"], "url": r["link"],
                    "snippet": r["snippet"]} for r in organic[:5]]
        verdict = judge_with_llm(claim, sources)
        report.append({
            "claim": claim,
            "verdict": verdict["label"],
            "confidence": verdict["confidence"],
            "sources": [s["url"] for s in sources],
        })
    return report


if __name__ == "__main__":
    results = fact_check("https://www.youtube.com/watch?v=VIDEO_ID")
    for row in results:
        print(f"[{row['verdict']}] {row['claim']}")
        for url in row["sources"]:
            print(f"    {url}")

JavaScript Example

JavaScript
const API_KEY = "sk_live_...";
const HEADERS = {
  Authorization: `Bearer ${API_KEY}`,
  "Content-Type": "application/json",
};
const BASE = "https://api.scavio.dev/api/v1";

async function getMetadata(videoUrl) {
  const resp = await fetch(`${BASE}/youtube/metadata`, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify({ query: videoUrl }),
  });
  if (!resp.ok) throw new Error(`metadata ${resp.status}`);
  return resp.json();
}

async function groundClaim(claim) {
  const resp = await fetch(`${BASE}/google`, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify({ query: claim, light_request: false }),
  });
  if (!resp.ok) throw new Error(`google ${resp.status}`);
  return resp.json();
}

// Replace these two with real LLM calls (Claude, etc.).
async function extractClaimsWithLLM(text) {
  throw new Error("not implemented");
}
async function judgeWithLLM(claim, sources) {
  throw new Error("not implemented");
}

async function factCheck(videoUrl) {
  const meta = await getMetadata(videoUrl);
  console.log(`Video: ${meta.title} (${meta.stats.views} views)`);

  const text = `${meta.title}\n\n${meta.description}`;
  const claims = await extractClaimsWithLLM(text);

  const report = [];
  for (const claim of claims) {
    const g = await groundClaim(claim);
    const organic = g.organic || [];
    const sources = organic.slice(0, 5).map((r) => ({
      title: r.title,
      url: r.link,
      snippet: r.snippet,
    }));
    const verdict = await judgeWithLLM(claim, sources);
    report.push({
      claim,
      verdict: verdict.label,
      confidence: verdict.confidence,
      sources: sources.map((s) => s.url),
    });
  }
  return report;
}

factCheck("https://www.youtube.com/watch?v=VIDEO_ID").then((results) => {
  for (const row of results) {
    console.log(`[${row.verdict}] ${row.claim}`);
    for (const url of row.sources) console.log(`    ${url}`);
  }
});

Expected Output

JSON
Video: The Truth About Solid-State Batteries (842113 views)
[supported] Solid-state cells reach higher energy density
    https://en.wikipedia.org/wiki/Solid-state_battery
    https://www.nature.com/articles/...
[unsupported] These batteries ship to consumers in 2026
    https://www.reuters.com/...
[mixed] Charge time drops to under five minutes
    https://ieeexplore.ieee.org/...

Related Tutorials

  • Build a Real-Time Fact-Checker That Grounds an LLM on Live Search

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

A Scavio API key (sk_live_...) from your dashboard; new accounts get 50 free credits.. Python 3.9+ with requests, or Node.js 18+ for the JavaScript version.. An LLM you can call for claim extraction and support judgement (Claude or similar).. A YouTube video URL or ID you want to check.. A Scavio API key gives you 50 free credits on signup.

Yes. The free tier includes 50 credits on signup, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Related Resources

Best Of

Best Google Search API in 2026

Read more
Best Of

Best Search APIs After Google I/O 2026 AI Mode Changes

Read more
Solution

Find YouTube Influencers via API Instead of Scraping

Read more
Use Case

YouTube Search API for Video SEO Research

Read more
Use Case

Google Programmable Search Engine Replacement

Read more
Solution

Replace Google Programmable Search Engine with Scavio API

Read more

Start Building

Pull a YouTube video's metadata, extract claims, and ground them against live Google results with the Scavio API. Working Python and JS.

Get Free API KeyRead the Docs
ScavioScavio

Real-time search API for AI agents. Search every platform, not just Google.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

  • Documentation
  • API Reference
  • Quickstart
  • MCP Integration
  • Python SDK

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative

Tools

  • JSON Formatter
  • cURL to Code
  • Token Counter
  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy