yt-search-python v2.2.1
Search YouTube videos, playlists, channels, comments, transcripts, recommendations, suggestions, and stream metadata without the YouTube Data API v3.
- Python 3.9+
- Sync API:
youtubesearchpython - Async API:
youtubesearchpython.future httpx>=0.28.1- No YouTube Data API key or quota
Installation
pip install yt-search-python
Search
from youtubesearchpython import VideosSearch
search = VideosSearch("Arijit Singh", limit=10)
print(search.result())
search.next()
print(search.result())
Live-only search is optional and backward compatible:
live = VideosSearch("news", limit=10, is_live=True)
print(live.result())
Async search loads its first page on the first await next() call:
import asyncio
from youtubesearchpython.future import VideosSearch
async def main():
search = VideosSearch("Arijit Singh", limit=10)
first = await search.next()
print(first)
second = await search.next()
print(second)
asyncio.run(main())
Video
from youtubesearchpython import Video
info = Video.getInfo("pnxL4OOzPEc")
formats = Video.getFormats("pnxL4OOzPEc")
PO token and visitor data can be supplied when required by the selected YouTube client/session:
formats = Video.getFormats(
"pnxL4OOzPEc",
po_token="YOUR_PO_TOKEN",
visitor_data="YOUR_VISITOR_DATA",
)
ResultMode.dict and ResultMode.json are supported by video APIs.
StreamURLFetcher
StreamURLFetcher no longer uses yt-dlp. It can process a Video.getFormats() result or fetch the format data from a video ID/link itself.
from youtubesearchpython import StreamURLFetcher
fetcher = StreamURLFetcher(po_token="YOUR_PO_TOKEN", visitor_data="YOUR_VISITOR_DATA")
url = fetcher.get("pnxL4OOzPEc", 18)
all_streams = fetcher.getAll("pnxL4OOzPEc")
Existing dictionary input remains supported:
from youtubesearchpython import Video, StreamURLFetcher
formats = Video.getFormats("pnxL4OOzPEc")
result = StreamURLFetcher().getAll(formats)
print(result["streams"])
print(result["unresolved"])
Direct URLs and cipher entries that already contain a usable signature are returned without yt-dlp. Formats that still require YouTube's encrypted player-JavaScript signature deciphering are returned under unresolved instead of being presented as working URLs. URLs that still contain an n parameter are marked with throttled=True so callers can make an informed choice rather than silently receiving a falsely-deciphered URL.
Playlists
Regular playlists and YouTube Mix/Radio playlists (RD...) use YouTube's native Innertube endpoints.
from youtubesearchpython import Playlist
normal = Playlist.get("PLRBp0Fe2GpgmsW46rJyudVFlY6IYjFBIK")
mix = Playlist.get("https://youtube.com/playlist?list=RDpnxL4OOzPEc&playnext=1")
Mix results preserve YouTube's returned song order. Duplicate video IDs are removed without re-sorting the result. Generic comment/engagement continuation tokens from /next responses are not treated as playlist continuations.
For regular playlists, instantiate Playlist(link) and call getNextVideos() for continuation pages.
Recommendations
from youtubesearchpython import Recommendations
related = Recommendations.get("pnxL4OOzPEc")
Recommendation results preserve YouTube's response order, skip the source video, remove duplicate video IDs stably, and normalize thumbnails against each video's ID.
Suggestions
from youtubesearchpython import Suggestions
print(Suggestions.get("Guru Randhawa"))
YTS_PROXY and YTS_IDENTITY_TOKEN environment variables are supported by the suggestions transport.
Comments, transcripts, channels and hashtags
from youtubesearchpython import Comments, Transcript, Channel, Hashtag
comments = Comments.get("pnxL4OOzPEc")
transcript = Transcript.get("pnxL4OOzPEc", params="en")
channel = Channel.get("UC_x5XG1OV2P6uZZ5FSM9Ttw")
hashtag = Hashtag.get("music", limit=10)
Transcript retrieval first uses YouTube's native caption/player flow. The optional transcript extra keeps the legacy yt-dlp caption fallback available:
pip install 'yt-search-python[transcript]'
HTTP lifecycle
The library uses one canonical httpx transport layer. Idle keep-alive retention is disabled to avoid stale pooled sockets in long-running bots/services.
Sync shutdown:
# Optional forced teardown only
from youtubesearchpython import close_clients
close_clients()
Async shutdown:
# Optional forced teardown only
from youtubesearchpython.future import aclose_clients
await aclose_clients()
Proxy requests use scoped clients that are closed after each request. Temporary downloaded cookie files are also ownership-tracked and cleaned without deleting user-owned cookie files.
Main API
Search:
SearchVideosSearchChannelsSearchPlaylistsSearchCustomSearchChannelSearch
Content:
VideoPlaylistChannelCommentsTranscriptHashtagSuggestionsRecommendations
Streaming:
StreamURLFetcher
Utilities:
ResultModeSearchModeVideoUploadDateFilterVideoDurationFilterVideoSortOrderChannelRequestType
Compatibility notes
youtubesearchpython.futureis the supported async namespace.- Legacy
SearchVideosandSearchPlaylistsimports remain available. - YouTube's internal response structures and anti-abuse requirements can change without notice.
- A PO token does not replace player JavaScript signature or
n-challenge transformation when YouTube requires those for a format.
License
MIT. See LICENSE.
Current maintainer: Prakhar Shukla / BillaSpace. Original project by Hitesh Kumar Saini (alexmercerind).
Optional PO token environment variables
Video and StreamURLFetcher keep their existing arguments, but can also read credentials from the environment when explicit values are not passed:
export YT_PO_TOKEN="..."
export YT_VISITOR_DATA="..."
Aliases YOUTUBE_PO_TOKEN and YOUTUBE_VISITOR_DATA are also supported. Explicit function/class arguments always take precedence over environment values.
Python compatibility
- Python 3.9+
- Runtime-tested on Python 3.13.5
- Audited against Python 3.14 asyncio removals/deprecations; the library uses
asyncio.get_running_loop()and does not depend on the deprecated event-loop policy APIs. - HTTP transport uses the tested
httpx>=0.28.1,<1.0range.
HTTP clients are managed internally. Normal sync applications require no explicit shutdown call, and async clients are closed automatically when their owning event loop shuts down gracefully (including asyncio.run()). close_clients() and aclose_clients() remain available only for optional forced teardown, tests, or unusual lifecycle control.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file yt_search_python-2.2.1.tar.gz.
File metadata
- Download URL: yt_search_python-2.2.1.tar.gz
- Upload date:
- Size: 270.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3522133778639621aa7d3d4c191b526391ad231fe6cf5f50abf0134afcff1cd
|
|
| MD5 |
d5faf6be82aeb078ceda91cc0e934ecd
|
|
| BLAKE2b-256 |
35bd3fe179de3f4f1e97a1c08759587d0569a2b2e127fb328794f3a92210f197
|
File details
Details for the file yt_search_python-2.2.1-py3-none-any.whl.
File metadata
- Download URL: yt_search_python-2.2.1-py3-none-any.whl
- Upload date:
- Size: 44.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58f81900af26f557ace70928012cd2b838e260d336d48b0cd22056bb90959b63
|
|
| MD5 |
8d819eaa012092d97bfaf5609a68d3ec
|
|
| BLAKE2b-256 |
159617354edf4675c0954f68bcb704204763a1524a8f71051e8ae2c8737a7cc0
|