Python SDK

The stophy package for Python: a client for search, video details, transcripts, comments, channels, and playlists.

Call the Stophy API from Python without wiring up HTTP requests. The stophy package gives you a Stophy class over every REST endpoint. It returns the same response envelope as the API reference.

Install

pip install stophy

Requires Python 3.9 or later.

Initialize

Create one client and reuse it. Pass your API key explicitly and keep it in an environment variable, never in source.

import os
from stophy import Stophy

stophy = Stophy(os.environ["STOPHY_API_KEY"])

Keep keys out of source code. Store them in environment variables and never commit them to git. See Authentication.

Make a request

Every method returns the standard response envelope as a dict. Read data for the result, or read creditsRemaining, requestId, and cacheState off the top level.

result = stophy.video(
    type="transcript",
    video_url="https://www.youtube.com/watch?v=D7liwdjvhWc",
)

print(result["data"]["text"])  # full transcript as a string

The returned dict matches the response envelope:

{
    "success": True,
    "requestId": str,
    "cacheState": "hit" | "miss",
    "creditsUsed": int,
    "creditsRemaining": int,
    "warning": str,  # present only when a result is partial or degraded
    "data": dict,
}

Methods

Arguments are keyword-only and snake_case. The SDK maps them to the API's field names for you, so video_url becomes videoUrl, continuation_token becomes continuationToken, and so on. Response keys stay as the API returns them, so you read data["continuationToken"] and data["items"][0]["repliesToken"].

MethodEndpointDescription
stophy.video(...)POST /v1/videoDetails, transcript, comments, replies, or live chat (set type)
stophy.search(...)POST /v1/searchSearch with filters for type, sort, date, duration, features
stophy.channel(...)POST /v1/channelChannel metadata and content by tab
stophy.playlist(...)POST /v1/playlistPlaylist items, paginated
stophy.credits()GET /v1/creditsCurrent credit balance
stophy.logs(...)GET /v1/logsRecent request logs
stophy.usage(...)GET /v1/usageDaily credit and request counts

video() is overloaded on type, so the returned data is typed for the variant you ask for (transcript, comments, details, replies, livechat).

Examples

# Search
results = stophy.search(q="typescript tutorial", sort_by="popularity", duration="long")["data"]

# Channel videos
channel = stophy.channel(channel_url="https://www.youtube.com/@mkbhd", tab="video")["data"]

# Comments, then replies to the first comment
comments = stophy.video(type="comments", video_url=url, sort_by="top")
token = comments["data"]["items"][0].get("repliesToken")
if token:
    replies = stophy.video(type="replies", continuation_token=token)

# Autocomplete

# Account
print(stophy.credits()["data"]["credits"])

Pagination

Comments, replies, live chat, search, channel tabs, and playlists return a continuationToken. Pass it back as continuation_token to fetch the next page, and stop when it is None.

token = None

while True:
    kwargs = {"video_url": "https://www.youtube.com/watch?v=D7liwdjvhWc", "type": "comments"}
    if token:
        kwargs["continuation_token"] = token

    data = stophy.video(**kwargs)["data"]
    print(data["items"])

    token = data.get("continuationToken")
    if not token:
        break

Error handling

Non-2xx responses raise StophyError, carrying status, code, the message, and request_id. Branch on code so unknown codes fall through to your default case (see Error handling).

import os
from stophy import Stophy, StophyError

stophy = Stophy(os.environ["STOPHY_API_KEY"])

try:
    result = stophy.video(
        type="details",
        video_url="https://www.youtube.com/watch?v=D7liwdjvhWc",
    )
    print(result["data"])
except StophyError as err:
    # err.status, err.code, str(err), err.request_id
    if err.code == "INSUFFICIENT_CREDITS":
        pass  # top up from dashboard
    elif err.code == "CONCURRENCY_LIMITED":
        pass  # too many requests in flight; retry once one finishes
    elif err.code == "UNAUTHORIZED":
        pass  # check your API key
    else:
        print(err.status, err.code, err)

Next steps

On this page