YouTube Class — ytscrape High-Level Scraping API Reference¶
Complete reference for the YouTube facade class — the primary entry point for searching, fetching videos, channels, comments, and transcripts.
The YouTube class is the main entry point for every scraping task in ytscrape. It is a thin facade over InnerTubeClient, the paginated result types, and the data models. You construct one instance, call methods on it, and let ytscrape handle authentication headers, pagination, and response parsing.
In most cases a zero-argument YouTube() call is all you need. Pass keyword arguments only when you want to target a specific locale, adjust the request timeout, or inject a pre-built InnerTubeClient (for example when running tests or routing traffic through a proxy).
from ytscrape import YouTube, SearchFilter
with YouTube() as yt:
for video in yt.search("python", filter=SearchFilter.VIDEOS, max_results=20):
print(video.title, video.url)
details = yt.video("dQw4w9WgXcQ")
print(details.title, details.views)
transcript = yt.transcript("dQw4w9WgXcQ", languages=["en"])
print(transcript.text[:200])
Constructor¶
YouTube(
*,
client: InnerTubeClient | None = None,
locale: Locale | None = None,
language: Language | str = "en",
region: Country | str = "US",
timeout: float = 30.0,
)
All arguments are keyword-only.
client(InnerTubeClient | None)-
A pre-built
InnerTubeClientto use instead of creating a new one. When provided, thelocale,language,region, andtimeoutarguments are ignored. Useful when you want to share a session across multipleYouTubeinstances or inject a custom client for testing. locale(Locale | None)-
A
Localeobject that bundles language and country together. When provided, thelanguageandregionarguments are ignored. Omit it to let the client build aLocalefrom the individuallanguageandregionvalues. language(Language | str)-
The
hl(host language) value sent in every InnerTube request. Accepts aLanguageenum member or a raw ISO 639-1 code such as"fr"or"de". Ignored whenlocaleis provided. region(Country | str)-
The
gl(geolocation) value sent in every InnerTube request. Accepts aCountryenum member or a raw ISO 3166-1 alpha-2 code such as"GB"or"DE". Ignored whenlocaleis provided. timeout(float)-
Per-request timeout in seconds applied to every HTTP call made by the default client. Ignored when
clientis provided.
Properties¶
client¶
The underlying InnerTubeClient instance. Useful when you need to call
low-level endpoints directly or inspect the session state without bypassing the facade.
locale¶
The Locale (language + country pair) that is being used for all requests. This is
a shortcut for yt.client.locale.
Methods¶
search¶
Search YouTube and return a lazily-paginated SearchResults object.
def search(
self,
query: str,
*,
filter: SearchFilter | str = SearchFilter.ALL,
max_results: int | None = None,
) -> SearchResults
query(str) required-
The search query string.
filter(SearchFilter | str)-
Narrows results to a specific content type. Accepts a
SearchFilterenum member (ALL,VIDEOS,CHANNELS,PLAYLISTS) or its lowercase string value ("all","videos","channels","playlists"). max_results(int | None)-
Optional cap on the total number of items yielded when iterating over the returned
SearchResults.Nonemeans iterate until YouTube runs out of pages.
Returns: SearchResults — a lazy iterable that transparently fetches
continuation pages on demand.
from ytscrape import YouTube, SearchFilter
yt = YouTube()
# Iterate over the first 50 video results
for video in yt.search("python tutorial", filter=SearchFilter.VIDEOS, max_results=50):
print(video.title, video.url)
video¶
Fetch detailed metadata for a single video.
video(str) required-
A video id or any YouTube URL that contains one. Supported URL formats include
watch?v=,youtu.be/,/shorts/, and/embed/.
Returns: VideoDetails — rich metadata including title, description,
view count, like count, upload date, and channel info.
from ytscrape import YouTube
yt = YouTube()
# Pass a full URL or just the 11-character video id
details = yt.video("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
print(details.title)
print(details.views)
print(details.channel.title)
channel¶
Fetch detailed metadata for a single channel.
channel(str) required-
A channel id starting with
UC, a@handle, or any YouTube channel URL. Supported formats include/channel/UC…,/@handle,/c/name, and/user/name.
Returns: ChannelDetails — includes title, description,
subscriber count, video count, and channel id.
from ytscrape import YouTube
yt = YouTube()
# Using a handle
channel = yt.channel("@RickAstleyYT")
print(channel.title)
print(channel.subscribers)
print(channel.description)
comments¶
Collect comments for a video and return a lazily-paginated CommentThread.
def comments(
self,
video: str,
*,
max_results: int | None = None,
include_replies: bool = False,
sort: CommentSort | str = CommentSort.TOP,
) -> CommentThread
video(str) required-
A video id or any YouTube URL that contains one (
watch?v=,youtu.be/,/shorts/,/embed/are all supported). max_results(int | None)-
Optional cap on the total number of comments yielded when iterating. When
include_repliesisTrue, replies count toward this limit too. include_replies(bool)-
When
True, replies to each top-level comment are also collected. Each reply is yielded immediately after the comment it belongs to and has itsis_replyattribute set toTrue. sort(CommentSort | str)-
The order in which comments are fetched.
CommentSort.TOPmirrors YouTube's "Top comments" view but intentionally omits less relevant comments and potential spam.CommentSort.NEWEST(or"newest") returns every comment. Use"newest"when completeness matters.
Returns: CommentThread — a lazy iterable that pages through comments on
demand.
Raises: ParseError — if the comments section cannot be found (e.g. comments are disabled).
Warning
CommentSort.TOP (the default) omits some comments — YouTube intentionally hides low-relevance
results and potential spam from this view. Use sort="newest" when you need a complete collection.
from ytscrape import YouTube, CommentSort
with YouTube() as yt:
# Collect all comments, including replies, newest first
for comment in yt.comments(
"https://youtu.be/dQw4w9WgXcQ",
sort=CommentSort.NEWEST,
include_replies=True,
max_results=200,
):
prefix = " ↳" if comment.is_reply else ""
print(f"{prefix} {comment.author}: {comment.text[:80]}")
transcript¶
Fetch a transcript (captions track) for a video.
def transcript(
self,
video: str,
*,
languages: list[str] | tuple[str, ...] = ("en",),
preserve_formatting: bool = False,
) -> Transcript
video(str) required-
A video id or any YouTube watch URL.
languages(list[str] | tuple[str, ...])-
Preferred language codes tried in order, e.g.
["uk", "en"]. Manually created captions are preferred over auto-generated ones within each language, following the same behaviour as youtube-transcript-api. preserve_formatting(bool)-
When
True, a small set of HTML formatting tags (<i>,<b>, etc.) are preserved inside snippet text. By default all tags are stripped.
Returns: Transcript — the full transcript with
.text (plain string) and .snippets (list of timed TranscriptSnippet objects).
from ytscrape import YouTube
yt = YouTube()
# Try Ukrainian first, fall back to English
transcript = yt.transcript("dQw4w9WgXcQ", languages=["uk", "en"])
print(transcript.language)
print(transcript.text[:300])
# Access individual timed snippets
for snippet in transcript.snippets:
print(f"[{snippet.start:.1f}s] {snippet.text}")
transcripts¶
List all available caption tracks for a video without downloading any of them.
video(str) required-
A video id or any YouTube watch URL.
Returns: TranscriptList — an iterable of
TranscriptTrack objects. Use .find_transcript() to locate a specific track, and .fetch() or
.translate() on a track to download it.
from ytscrape import YouTube
yt = YouTube()
track_list = yt.transcripts("dQw4w9WgXcQ")
for track in track_list:
print(
track.language, track.language_code, "auto" if track.is_generated else "manual"
)
# Find a specific track and fetch it
track = track_list.find_transcript(["en"])
transcript = track.fetch()
print(transcript.text[:200])
close¶
Close the underlying HTTP session and release all associated resources.
Returns: None
Tip
Prefer the context manager form (with YouTube() as yt: …) over calling close() manually — it
guarantees cleanup even when an exception is raised inside the block.
from ytscrape import YouTube
yt = YouTube()
try:
details = yt.video("dQw4w9WgXcQ")
print(details.title)
finally:
yt.close()
Context manager support¶
YouTube implements the context manager protocol (__enter__ / __exit__), so you can use it
in a with statement. __exit__ calls close() automatically, even when an exception is raised
inside the block.
from ytscrape import YouTube, SearchFilter
with YouTube(language="de", region="DE") as yt:
for video in yt.search("python kurs", filter=SearchFilter.VIDEOS, max_results=10):
print(video.title, video.url)
# HTTP session is closed automatically here
AsyncYouTube¶
AsyncYouTube is the async counterpart of YouTube. Method names and arguments match the sync facade; call sites use await and async for. Requires the optional extra: pip install "ytscrape[async]".
import asyncio
from ytscrape import AsyncYouTube, SearchFilter
async def main() -> None:
async with AsyncYouTube(
language="en",
region="US",
max_concurrency=8,
max_retries=3,
backoff_factor=0.5,
timeout=30.0,
) as yt:
results = await yt.search(
"python",
filter=SearchFilter.VIDEOS,
max_results=10,
)
async for video in results:
print(video.title, video.url)
details = await yt.video("dQw4w9WgXcQ")
channel = await yt.channel("@YouTube")
thread = await yt.comments("dQw4w9WgXcQ", max_results=50, sort="newest")
async for comment in thread:
print(comment.author)
transcript = await yt.transcript("dQw4w9WgXcQ", languages=["en"])
tracks = await yt.transcripts("dQw4w9WgXcQ")
asyncio.run(main())
Constructor extras (async only)¶
| Argument | Default | Description |
|---|---|---|
client |
None |
Pre-built AsyncInnerTubeClient. When set, locale/timeout/concurrency kwargs for the default client are ignored. |
max_concurrency |
8 |
Cap on concurrent HTTP requests (default client). |
max_retries |
3 |
Retry budget for transient HTTP failures. |
backoff_factor |
0.5 |
Base delay for exponential backoff. |
timeout |
30.0 |
Per-request timeout in seconds. |
Locale arguments (locale, language, region) behave like on YouTube.
Methods (async)¶
| Method | Returns |
|---|---|
await yt.search(query, *, filter=..., max_results=...) |
AsyncSearchResults |
await yt.video(video) |
VideoDetails |
await yt.channel(channel) |
ChannelDetails |
await yt.comments(video, *, max_results=..., include_replies=..., sort=...) |
AsyncCommentThread |
await yt.transcript(video, *, languages=..., preserve_formatting=...) |
Transcript |
await yt.transcripts(video) |
TranscriptList |
await yt.aclose() / await yt.close() |
None |
Properties client and locale mirror the sync API (client is an AsyncInnerTubeClient).
AsyncSearchResults / AsyncCommentThread¶
Same pagination contract as SearchResults / CommentThread:
async for item in results:— lazy pagesawait results.fetch_next_page()— manual page loadresults.has_more— continuation available
See the Async API guide for concurrency patterns and multi-video asyncio.gather examples.