Changelog¶
All notable changes to ytscrape will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
[2.2.0] — 2026-10-18¶
Added¶
Transcript.to_srt()andto_vtt()for subtitle export, with UTF-8dump_srt()/dump_vtt()helpers accepting paths or text streams (#18).- Optional MCP server: install with
ytscrape[mcp]and runytscrape-mcp(orpython -m ytscrape.mcp_server) to expose search, video/channel metadata, channel uploads, comments (replies included) and transcripts as read-only Model Context Protocol tools. stdio by default, plus--transport streamable-http|ssefor hosted setups;--language,--regionand--timeoutflags mirror theYouTubefacade. All tools carry read-only tool annotations (readOnlyHint,openWorldHint,idempotentHint) so MCP clients can auto-approve them. - MCP server proxy support:
--proxy(both schemes) plus--http-proxy/--https-proxyfor per-scheme routing; the standardHTTP_PROXY/HTTPS_PROXY/NO_PROXYenvironment variables are honoured as well. - MCP responses are size-capped (
truncated+hint). List tools and transcripts returnhas_more/next_cursorinstead of an unbounded dump.max_resultsis capped at 50.filter,sortanddetail(concise/full) are enums.get_video/get_channeldefault to a concise projection. Cursors are depth-capped at 1 000 items (each page re-reads the listing from the start),list_transcriptsreturns the same{items, count, has_more, next_cursor, truncated}envelope as the other list tools, and a transcript snippet cut mid-text says so inhint.
[2.1.0] — 2026-10-08¶
Added¶
VideoDetails.scheduled_at: planned start time of scheduled premieres / upcoming live streams; shown asScheduledinytscrape video(#16).- First-class proxy support: new
proxiesargument onYouTube,AsyncYouTube,InnerTubeClientandAsyncInnerTubeClientaccepting arequests-style mapping (e.g.{"https": "http://user:pass@host:8080"}). The sync clients expose a settableproxiesproperty for rotating proxies at runtime (e.g. after aBotDetectederror) (#17).
Changed¶
VideoDetails.published/published_at(the publication date) are nowNonefor scheduled videos that are not published yet, instead of the planned start time (#16). Docs and README highlight the publication date.
[2.0.0] — 2026-10-02¶
Added¶
- Reliability:
RetryPolicy(exponential backoff, jitter,Retry-After),RateLimiter/min_interval,ContextCachewith TTL and a globalDEFAULT_CONTEXT_CACHEkeyed by(language, region). New client kwargsretry,rate_limiter,min_interval,context_cache. - Exceptions:
YtScrapeErrorbase (aliasYtScraperError),RateLimited,BotDetected(aliasCaptchaRequired),ConsentRequired,VideoUnavailable,AgeRestricted;RequestError.status_code/.url. - Debug logging on the
ytscrapelogger (requests, retries, timings). YouTube.channel_videos()/AsyncYouTube.channel_videos()returning lazyChannelVideos/AsyncChannelVideos.- Navigation helpers:
Video.details()/comments()/channel_details(),VideoDetails.comments()/channel_details(),Channel.details()/videos(),ChannelDetails.videos();UnboundModelErrorfor unbound models. Thumbnail(url, width, height)andthumbnailstuples on all models.VideoDetails.published_at/uploaded_atdatetimes;Video.published_at.- Parse helpers
parse_count,parse_relative_time,parse_date. - CI: pytest matrix 3.10–3.14 with coverage (Codecov) and mypy, nightly live tests, Dependabot; publishing requires passing tests.
- Docs: reliability, models & navigation, channel videos, recipes, FAQ, migration guide.
Changed (breaking)¶
Video.viewsisint | None(raw text inviews_text).Video.publishedremoved →published_text+published_at.Channel.subscribers/video_count,Playlist.video_count,ChannelDetails.subscribers/video_count/view_countareint | Nonewith*_textcounterparts.video()raisesVideoUnavailable/AgeRestricted/BotDetected.- Exports serialise datetimes as ISO 8601 and thumbnails as lists of dicts.
Fixed¶
- Examples updated for numeric counts.
[1.0.1] - 2026-08-19¶
Added¶
- Paginator export:
SearchResultsandCommentThreadexposeto_json()/to_csv()/dump_json/dump_csv. Async counterparts useawait results.to_json()(and the same dump helpers). Streams honourmax_resultsand write a JSON array or CSV table of items.
[1.0.0] - 2026-08-14¶
Changed¶
- CLI wordmark matches the brand logo: red
yt, whitescrape. - CLI
--format/--output/--language/--regionwork after the subcommand as well (ytscrape search "JS" --format csv). - Search parsing uses only classic InnerTube renderers
(
videoRenderer/channelRenderer/playlistRenderer).lockupViewModelhelpers andfrom_lockupfactories are gone.
Added¶
- Brand assets under
docs/assets/: light/darkytscrapewordmarks in the README header and on the docs home page, matching light/dark icons as the docs-site logo / favicon, and an animated CLI demo GIF in the README (CLI cheatsheet) and the CLI overview page. - JSON / CSV export: models have
to_dict()/to_json()/to_csv()(anddump_json/dump_csv). Collections usedumps_json/dumps_csv. CLI:--format json|csvand--output FILE. - Colourful CLI: mini
▶ ytscrapewordmark, boxed tables for search / video / channel / comments / transcripts.--format plainkeeps the old TSV / key-value output;--no-color/NO_COLORdisable ANSI. Search tables omit the unusedPublishedcolumn when results are channels (or other non-video items). Table columns stay aligned when titles contain emoji or other wide characters (♥ stays single-width; emoji presentation such as ❤️ is double-width). Newlines in comments are flattened so they cannot break a table row. Search tables include aURLcolumn for video watch links and channel pages. Table mode shows a braille spinner on stderr while a request is in flight. - Richer video metadata: search
Videofillsduration/views/published/descriptionfrom classicvideoRendererfields (lengthText,viewCountText,publishedTimeText,descriptionSnippet). VideoDetailsnow also reads player microformat:published,upload_date,category,owner_profile_url,embed_url,is_private,is_upcoming,allow_ratings,is_family_safe,available_countries.
[0.1.5] - 2026-08-11¶
Added¶
- ⚡ Async API:
AsyncYouTube/AsyncInnerTubeClientwith the same public surface as the sync facade (search,video,channel,comments,transcript/transcripts). Optional extra:pip install "ytscrape[async]"(httpx). - Shared parsing path for sync and async (
ytscrape.parsing+ models). - Async concurrency limit (
max_concurrency) and exponential backoff with jitter on 429 / 5xx / transport errors (max_retries,backoff_factor). - Async paginators:
AsyncSearchResults,AsyncCommentThread(async for). - Feature examples
01–09now include both sync and async paths (run_sync/run_async, CLI flag--async). - Concurrency-focused example
examples/10_async_concurrency.py. - Docs site updates: async guide (
docs/guides/async.md),docs/examples.md, plus installation, quickstart, advanced, pagination, comments, transcripts, API pages, and a leaner README that points at docs instead of duplicating long guides.
[0.1.4] - 2026-08-6¶
Added¶
- 📝 Transcripts / captions via
YouTube.transcript()andYouTube.transcripts(), modeled after youtube-transcript-api: ANDROID InnerTubeplayerfor caption tracks, timedtext XML download, language priority, manual-vs-ASR preference, optional server-sidetranslate(), and CLIytscrape transcript. - New types:
Transcript,TranscriptSnippet,TranscriptTrack,TranscriptList; errorsTranscriptsDisabled,NoTranscriptFound. - Example
examples/09_transcript.py. - 🖼️ Richer
ChannelDetails:photo(avatar),banner,country,joined_date,view_count, andlinksas a platform→URL dictionary (e.g.{"x": "…", "instagram": "…", "discord": "…"}). About-panel fields are loaded via the channel engagement-panel continuation. - 📺 Channel metadata with
YouTube.channel(channel). Pass a channel id (UC…), a@handle, or any channel URL (/channel/…,/@handle,/c/…,/user/…) and get a typedChannelDetailsmodel (title, description, handle, subscribers, video count, keywords/tags, avatar, vanity + RSS URLs, family-safe flag, available countries, external links). - 🔌 New low-level
InnerTubeClient.browse()/get_html()helpers used by channel resolution. - 🖥️ New CLI command:
python -m ytscrape channel <id|@handle|url>. - 📚 New example
examples/08_channel_details.py.
[0.1.3] - 2026-08-5¶
Added¶
- 💬 Collect the comments of a video with
YouTube.comments(video). Pass a video id or any YouTube URL and iterate over the returnedCommentThread; it transparently pages through every comment (and reply), just like search results. Comments are exposed as a newCommentmodel (author, text, like & reply counts, published time,is_reply). - ↳ Optional reply collection:
YouTube.comments(video, include_replies=True)now also expands the replies of every comment thread. Each reply hasis_reply=Trueand is yielded right after the comment it replies to; the CLI gained a matching--repliesflag. - 🖥️ New CLI command:
python -m ytscrape comments <video> [--max N] [--replies] [--sort top|newest]. - 🔀 New
sortoption for comment collection:YouTube.comments(video, sort=CommentSort.NEWEST)(orsort="newest"). The newCommentSortenum (TOP/NEWEST) is exported from the package top level, and the CLI gained a matching--sortflag. - 📚 New example
examples/07_video_comments.pyshowing how to collect comments (and their replies). - ❤️ Richer
Commentmodel: newheartflag (whether the video's creator hearted the comment) pluslike_count_text/reply_count_textfields that keep YouTube's raw counts, including abbreviations such as1.2Kthat the integerlike_count/reply_countcannot represent exactly.
[0.1.2] - 2026-07-29¶
Added¶
- 📚 New
examples/folder with short, runnable, self-contained scripts: searching videos (01_search_videos.py), channels & playlists (02_search_channels_playlists.py), fetching video details (03_video_details.py), pagination (04_pagination.py), language & region localisation (05_language_region.py) and error handling (06_error_handling.py), plus anexamples/README.mdindex. - 🏷️ PyPI version badge in the README linking to the project page on PyPI.
Changed¶
- 📝 Expanded the README with a link to the new
examples/folder right after the Quick start section.
[0.1.1] - 2026-07-29¶
Added¶
- 🔎 Search YouTube videos, channels and playlists via a clean
SearchFilterenum (no magicparamsstrings in your code). - 📄 Transparent pagination — iterate over results and continuation tokens are
handled for you;
max_resultscaps how many items you consume. - 🎬 Fetch detailed video metadata from a video id or any YouTube URL.
- 🌍 Language & country support (
hl/gl) through theLanguage,CountryandLocalevalue objects, validated withpycountry. - 🖥️ A tiny CLI:
python -m ytscrape ...and aytscrapeconsole script. - 📦 Automated PyPI publishing on version tags via the
.github/workflows/publish.ymlGitHub Action (Trusted Publishing / OIDC).