Skip to main content

YTAPI Python client

Python client for YTAPI: YouTube transcripts, video details, comments, search, channels and playlists over one HTTP API. It works from servers and cloud functions, where fetching YouTube directly tends to get blocked.

  • No dependencies beyond the standard library. Python 3.10+.
  • Typed responses (TypedDict), typed errors, automatic retries and pagination.
  • Reference: docs.ytapi.dev.

Install

pip install ytapi-sdk

The package is ytapi-sdk on PyPI, and you import it as ytapi.

Quickstart

Get a key at ytapi.dev. New accounts get 200 free credits, and no card is needed.

from ytapi import YTAPI

api = YTAPI()  # reads YTAPI_API_KEY (or YTAPI_KEY) from the environment
transcript = api.get_transcript("dQw4w9WgXcQ")
for segment in transcript["segments"][:3]:
    print(segment["start"], segment["text"])

By default you get the captions in the video's own language, as timed segments. A successful request uses 1 credit, and errors are free.

Examples

# Other formats. markdown, text, srt and vtt come back as a string.
srt = api.get_transcript("dQw4w9WgXcQ", format="srt")
spanish = api.get_transcript("dQw4w9WgXcQ", format="text", languages=["es", "*"])
words = api.get_transcript("dQw4w9WgXcQ", format="word_timestamps", word_level=True)

# Free: title, length, channel and the caption languages a video has.
basic = api.get_basic_info("dQw4w9WgXcQ")
# 1 credit: description, counts, chapters and more.
info = api.get_video_info("dQw4w9WgXcQ")

# Comments, top or newest first: 1 credit per page of about 20.
page = api.get_comments("dQw4w9WgXcQ", sort="top")
for comment in page["comments"]:
    print(comment["like_count"], comment["author"]["name"], comment["text"])
# A comment's replies, from its replies_cursor.
if page["comments"]:
    top = page["comments"][0]
    for reply in api.iter_comment_replies("dQw4w9WgXcQ", top.get("replies_cursor")):
        print("  ", reply["text"])

# The "most replayed" graph: 1 credit; free NotFoundError when a video has none.
heatmap = api.get_heatmap("dQw4w9WgXcQ")
for peak in heatmap.get("peaks", []):
    print(peak["start_seconds"], peak["intensity"])

# Channels take an @handle, a channel ID (UC...) or a URL.
channel = api.get_channel("@3blue1brown")
for video in api.iter_channel_videos("@3blue1brown", sort_by="popular"):
    print(video["video_id"], video["title"])

# Playlists, page by page or as an iterator.
for video in api.iter_playlist_videos("PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi"):
    print(video["video_id"], video["length_text"])

# Search: type is video, channel, playlist, shorts or movie.
page = api.search("rust async", type="video", upload_date="month", limit=10)
for hit in page["items"]:
    print(hit["title"])

# Search suggestions are free.
print(api.get_suggestions("nextjs")["suggestions"])

# Batch: up to 100 transcript or basic_info tasks per job.
job = api.create_batch(
    [
        {"id": "a", "type": "transcript", "video_id": "dQw4w9WgXcQ", "format": "text"},
        {"id": "b", "type": "basic_info", "video_id": "jNQXAC9IVRw"},
    ]
)
done = api.poll_batch(job["id"], timeout=120)
print(done["successful"], done["credits_deducted"])

The iterators (iter_playlist_videos, iter_channel_videos, iter_channel_playlists, iter_search, iter_comments, iter_comment_replies) follow next_cursor for you. Each page is a request and uses a credit. In a batch, each successful task uses 1 credit and failed tasks are free.

Errors

from ytapi import InsufficientCreditsError, NotFoundError, RateLimitedError, YTAPIError

try:
    api.get_transcript("xxxxxxxxxxx")
except NotFoundError as exc:
    print(exc.code)  # captions_disabled, comments_disabled, video_unavailable, ...
except RateLimitedError as exc:
    print(exc.code, exc.retry_after)  # rate_limited or daily_limit_exceeded
except InsufficientCreditsError:
    print("Out of credits: https://ytapi.dev/#pricing")
except YTAPIError as exc:
    print(exc.status, exc.code, exc)  # status 0 means a network error
Status Exception
401 AuthError
402 InsufficientCreditsError
404 NotFoundError
429 RateLimitedError
5xx ServerError
network error YTAPIError with status 0
other YTAPIError

Retries

The client retries a 429, a 5xx or a network error up to max_retries times (default 2). It backs off from 0.5 seconds, doubling up to 8, and waits longer when the server sends Retry-After. One case is not retried:

  • A 429 that asks for a long wait. The cutoff is max_retry_wait, default 60 seconds. This includes a free account's daily limit (daily_limit_exceeded), which lasts until 00:00 UTC. The client raises these right away instead of hanging your program.

create_batch sends an Idempotency-Key header (a new UUID per call, or pass idempotency_key=), so a retried submit returns the job it already created instead of starting and billing a second one. Pass your own key, such as an order ID, to make retrying the whole call safe as well.

Use YTAPI(max_retries=0) to turn retries off.

Releases

Each GitHub release publishes the matching version to PyPI through trusted publishing. The release tag must match the version in pyproject.toml, such as v0.1.0.

Tests

PYTHONPATH=src python3 -m unittest discover -s tests

The tests mock HTTP and need no network or API key.

License

MIT

Metadata

Release files for ytapi-sdk 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ytapi-sdk 0.3.0
File Size Uploaded
ytapi_sdk-0.3.0.tar.gz 18.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ytapi-sdk 0.3.0
File Interpreter ABI Platform
ytapi_sdk-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 32.1 kB

Release files / ytapi_sdk-0.3.0.tar.gz

Download URL ytapi_sdk-0.3.0.tar.gz
Size 18.7 kB
Tags Source
SHA-256 checksum
How to use checksums
2c31f19c579abba1ae6f1b07780bf3087501fd1b9c8d2bb7196f1cb0aab9e762
BLAKE2b-256 checksum
How to use checksums
6c10b6a78ecf42055974cc3eb29befb7d8eee5381a5d2aa0231dd0e123d931af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / ytapi_sdk-0.3.0-py3-none-any.whl

Download URL ytapi_sdk-0.3.0-py3-none-any.whl
Size 13.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e9d7a999d5118b36ea60e28a3bc7d56e47f9551bf3048fad6dc5a80570aff11e
BLAKE2b-256 checksum
How to use checksums
7cd93e40b62abf7299ed50119d7a2d89a19d371c571a628d898fe7a6ca98e094
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page