Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/vsmutok/ytscrape/llms.txt

Use this file to discover all available pages before exploring further.

YouTube is a thin facade over InnerTubeClient, which owns the requests.Session that performs every HTTP call. Injecting your own session is the single hook for proxies, retries, custom headers, caching, or unit-test mocks — none of the rest of the library needs to change.

Injecting a custom session

Build your requests.Session, configure it, then wrap it in an InnerTubeClient and pass that to YouTube:
import requests
from ytscrape import YouTube, InnerTubeClient

session = requests.Session()
# ... configure session here ...

client = InnerTubeClient(session=session, language="en", region="US")

with YouTube(client=client) as yt:
    print(next(iter(yt.search("python"))).title)
Any option you set on the session — headers, auth, cookies, adapters — is automatically used for every request ytscrape makes.

Proxies

Set session.proxies to route traffic through an HTTP or SOCKS proxy:
import requests
from ytscrape import YouTube, InnerTubeClient

session = requests.Session()
session.proxies = {"https": "http://user:pass@proxy:8080"}

client = InnerTubeClient(session=session, language="en", region="US")

with YouTube(client=client) as yt:
    print(next(iter(yt.search("python"))).title)

Retries with HTTPAdapter

Mount an HTTPAdapter with a Retry policy to automatically retry transient failures:
import requests
from requests.adapters import HTTPAdapter, Retry
from ytscrape import YouTube, InnerTubeClient

session = requests.Session()
session.proxies = {"https": "http://user:pass@proxy:8080"}
session.mount(
    "https://",
    HTTPAdapter(max_retries=Retry(total=5, backoff_factor=1)),
)

client = InnerTubeClient(session=session, timeout=15.0, language="en", region="US")

with YouTube(client=client) as yt:
    print(next(iter(yt.search("python"))).title)
backoff_factor=1 means the client waits 1 s, 2 s, 4 s, … between retries. See the urllib3 Retry documentation for the full set of options.

Custom timeout

Pass timeout (in seconds) to InnerTubeClient to override the default of 30 seconds. This timeout applies to every individual request:
client = InnerTubeClient(timeout=10.0, language="en", region="US")

with YouTube(client=client) as yt:
    details = yt.video("dQw4w9WgXcQ")
You can also set timeout directly on the default client by passing it to YouTube:
with YouTube(timeout=10.0) as yt:
    details = yt.video("dQw4w9WgXcQ")

Using InnerTubeClient directly

InnerTubeClient exposes the raw InnerTube endpoint wrappers (search, player, browse, next) when you need lower-level access. All of them return the parsed JSON dictionary from YouTube’s API:
from ytscrape import InnerTubeClient

with InnerTubeClient(language="en", region="US") as client:
    data = client.player("dQw4w9WgXcQ")
    print(data["videoDetails"]["title"])
Pass a fully configured InnerTubeClient to YouTube when you want to share the same session and context across all high-level calls:
client = InnerTubeClient(session=my_session, timeout=15.0)
yt = YouTube(client=client)

Testing with a fake session

Because InnerTubeClient accepts any requests.Session, you can inject a mock in tests so that no real network call ever happens:
from unittest.mock import MagicMock
import requests
from ytscrape import YouTube, InnerTubeClient

fake_session = MagicMock(spec=requests.Session)
# Configure fake_session.get / .post to return canned responses...

client = InnerTubeClient(session=fake_session)
yt = YouTube(client=client)
# All calls on `yt` now go through your mock.
Reuse a single YouTube instance across multiple operations. On the first call, the client fetches the YouTube home page to extract the InnerTube context (API key, client version, visitor data). Reusing the same instance keeps that context warm and avoids an extra round-trip on every subsequent call.
requests.Session is not thread-safe. If you run ytscrape from multiple threads, create a separate YouTube (and therefore a separate session) per thread rather than sharing one instance.

Build docs developers (and LLMs) love