EasyTranscriberEasyTranscriber

easytranscriber-sdk 0.1.0 · Python 3.10+

Python SDK reference

Use synchronous or asynchronous Python clients for YouTube transcripts, separate summaries, discovery, and comments. The SDK returns typed dictionaries and leaves pagination under your control.

Try the API — no card required

Install and authenticate

Install the published easytranscriber-sdk package with Python 3.10 or newer. Import it as easytranscriber_sdk. The differently named PyPI package easytranscriber is unrelated; do not install it for this API.

pip install easytranscriber-sdk

Create an API key in your dashboard using the API-key button above. Keys begin with et_. Pass it explicitly as api_key; the client does not automatically read environment variables. It sends Authorization: Bearer <api_key> and Accept: application/json. Keep keys in server-side environment variables, never browser code or source control. Empty or whitespace-only keys raise ValueError.

Get a transcript, then a separate summary

import os
from easytranscriber_sdk import EasyTranscriber

# Set EASYTRANSCRIBER_API_KEY in your environment first.
# Your application reads it; the SDK requires an explicit api_key.
with EasyTranscriber(api_key=os.environ["EASYTRANSCRIBER_API_KEY"]) as client:
    transcript = client.transcribe("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
    print(transcript["transcript"])
    print(transcript["credits_used"])

    # Separate request: costs 1 additional credit, even for cached transcripts.
    summary = client.summarize(
        transcript["transcript"],
        video_id=transcript["video_id"],
        language="English",
    )
    print(summary["summary"])

transcribe() does not generate a summary. summarize() is a separate, non-streaming API call and always costs an additional credit. Use dictionary access such as transcript["transcript"], not attribute access such as transcript.transcript.

Async client and connection cleanup

import asyncio
import os
from easytranscriber_sdk import AsyncEasyTranscriber

async def main() -> None:
    async with AsyncEasyTranscriber(
        api_key=os.environ["EASYTRANSCRIBER_API_KEY"]
    ) as client:
        latest = await client.channel_latest("@NASA")
        print(latest["videos"])
        balance = await client.credits()
        print(balance["balance"])

asyncio.run(main())

AsyncEasyTranscriber has the same constructor options, method parameters, and result models as EasyTranscriber; await every API method. Reuse a client for connection pooling. Context managers close connections even when an exception occurs.

Without a context manager, use client.close() for the synchronous client or await client.aclose() for the asynchronous client, ideally in finally. Both expose the boolean is_closed property. Create a new client after closing one. Async retry waits use non-blocking sleep, and cancellation propagates.

Client configuration

Only api_key: str is required. All other constructor parameters are keyword-only.

Options shared by synchronous and asynchronous Python clients
OptionDefaultBehavior
base_url: strhttps://www.easytranscriber.com/api/v1Complete API prefix; trailing slash is normalized. Use HTTPS for real API keys.
timeout: float | httpx.Timeout | None310.0HTTPX timeout in seconds per network operation, not a total deadline. Pass an httpx.Timeout for finer control, or None to disable timeouts.
max_retries: int2Additional attempts for HTTP 429 only (at most 3 attempts by default). Set 0 to disable. Must be a non-negative integer, not a bool.
retry_backoff: float0.5Initial exponential backoff in seconds, doubled after each retry. Finite and non-negative; bounded by max_retry_delay.
max_retry_delay: float60.0Maximum wait in seconds. Finite and non-negative. A longer server Retry-After surfaces the 429 instead of retrying early.

The default timeout allows for the server processing window; backoff waits and retry attempts add time. Redirects are not followed. Invalid retry configuration raises ValueError.

All ten methods

Signatures below apply to both clients; the async versions must be awaited. The * marks keyword-only options. Optional None values are omitted from requests. REST paths are relative to /api/v1: POST parameters become JSON fields, while GET parameters become query parameters.

transcribe

transcribe(url: str) -> TranscriptResponse

POST /transcribe0 cached; 1 new, or 2 over 2 hours

Pass a YouTube video URL. Returns the transcript only, not a summary. Maximum video duration: 4 hours.

summarize

summarize(transcript: str, *, video_id: str | None = None, language: str | None = None) -> SummaryResponse

POST /summarize1 additional credit per call

Pass transcript text, with an optional video ID and summary language. Use a supported display name such as English or Spanish, or Auto—not an ISO code. None omits the option. Returns a complete JSON summary, not a stream. A cached transcript does not make summarization free.

credits

credits() -> CreditsResponse

GET /creditsFree

Read the current credit balance. No arguments and no credits_used field.

resolve_channel

resolve_channel(channel: str) -> ChannelResponse

GET /youtube/channel/resolveFree

Resolve a channel @handle, channel URL, or UC… channel ID to channel details. Subscribers is a nullable string, not an integer.

channel_latest

channel_latest(channel: str) -> ChannelLatestResponse

GET /youtube/channel/latestFree

Get recent uploads from a channel RSS feed. Accepts a @handle, channel URL, or UC… channel ID. No pagination or credits_used field.

channel_videos

channel_videos(channel: str, *, page_token: str | None = None) -> ChannelVideosResponse

GET /youtube/channel/videos1 credit per page

List channel uploads. Channel accepts a @handle, channel URL, or UC… channel ID. Fetch further pages explicitly.

playlist_videos

playlist_videos(playlist: str, *, page_token: str | None = None) -> PlaylistVideosResponse

GET /youtube/playlist/videos1 credit per page

List videos from a playlist ID or YouTube playlist URL. Fetch further pages explicitly.

comments

comments(video: str, *, max_results: int = 20, order: CommentOrder = "relevance", page_token: str | None = None) -> CommentsResponse

GET /youtube/comments1 credit per page

Pass a YouTube video URL or ID. CommentOrder is Literal["relevance", "time"]. The server bounds max_results to 1–100 (zero falls back to 20). Replies contain the replies returned by YouTube, not necessarily every reply.

Typed dictionaries, not model objects

All models below are exported from easytranscriber_sdk as TypedDict contracts. They describe plain JSON dictionaries, with no data envelope and no runtime schema validation. Unknown fields are preserved. JSON null becomes None; dates stay strings. Nullable fields are not the same as omitted fields.

Every exported Python response and nested model field
ModelFields and types
TranscriptResponsevideo_id: str; video_title: str | None; transcript: str; method: str; cached: bool; credits_used: int
SummaryResponsesummary: str; video_id: str | None; credits_used: int
CreditsResponsebalance: int
SearchResultvideo_id: str | None; channel_id: str; title: str; channel: str; published_at: str; thumbnail: str | None
SearchResponseresults: list[SearchResult]; next_page_token: str | None; credits_used: int
ChannelSearchResponseAll SearchResponse fields, plus channel_id: str
ChannelResponsechannel_id: str; name: str; handle: str | None; subscribers: str | None; thumbnail: str | None
LatestVideovideo_id: str; title: str; published_at: str; thumbnail: str
ChannelLatestResponsechannel_id: str; videos: list[LatestVideo]
Videovideo_id: str; title: str; published_at: str; thumbnail: str | None
VideosPagevideos: list[Video]; next_page_token: str | None; total_results: int | None; credits_used: int
ChannelVideosResponseAll VideosPage fields, plus channel_id: str
PlaylistVideosResponseAll VideosPage fields, plus playlist_id: str
CommentReplyauthor: str; text: str; likes: int; published_at: str; updated_at: str
CommentAll CommentReply fields, plus reply_count: int; replies: list[CommentReply]
CommentsResponsevideo_id: str; comments: list[Comment]; next_page_token: str | None; total_results: int | None; credits_used: int

method is an unrestricted string, not an enum. LatestVideo.thumbnail is a string, whereas Video.thumbnail and SearchResult.thumbnail can be None. Free responses do not add a synthetic credits_used field. The exported option aliases are SearchType and CommentOrder, as shown in the method reference.

Explicit, credit-aware pagination

import os
from easytranscriber_sdk import EasyTranscriber

with EasyTranscriber(api_key=os.environ["EASYTRANSCRIBER_API_KEY"]) as client:
    page = client.channel_videos("@NASA")  # 1 credit
    for video in page["videos"]:
        print(video["video_id"], video["title"])

    # Deliberate second request, not an automatic iterator: another credit.
    token = page["next_page_token"]
    if token is not None:
        next_page = client.channel_videos("@NASA", page_token=token)
        print(next_page["videos"])

The SDK never fetches another page automatically. Pass next_page_token unchanged as page_token=; HTTPX encodes it. None means there is no next page. The same pattern applies to search, channel_search, playlist_videos, and comments. Every requested page costs one credit. channel_latest has no page token.

Errors, retries, and uncertain outcomes

import os
import httpx
from easytranscriber_sdk import APIError, APIResponseError, EasyTranscriber

with EasyTranscriber(
    api_key=os.environ["EASYTRANSCRIBER_API_KEY"], max_retries=2
) as client:
    try:
        result = client.transcribe("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
        print(result["transcript"])
    except APIError as error:
        print(error.status, error.code, error.message)
        # Fix 400/401 input or credentials; 402 requires credits.
        # A surfaced 429 exhausted retries or requested too long a wait.
    except APIResponseError as error:
        print("Unexpected successful response:", error.status)
        # Do not blindly repeat a potentially billed request.
    except httpx.TimeoutException:
        print("Timed out; the server may already have charged credits.")
    except httpx.RequestError as error:
        print("Transport failure; outcome unknown:", error)
        # Check balance/history before deciding whether to try again.

Non-success HTTP responses raise APIError with status: int, code: str, and message: str. The SDK extracts those strings from the API error envelope:

{"error":{"code":"insufficient_credits","message":"Insufficient credits"}}
  • 400 · invalid_request: correct the missing or invalid input before trying again.
  • 401 · unauthorized: check your API key.
  • 402 · insufficient_credits: check your balance and add credits.
  • 429 · rate_limited: only this HTTP status is eligible for automatic retry.

If an error body lacks usable code or message strings, the corresponding fallbacks are http_error and the HTTP reason phrase (or Request failed). HTML error bodies are not included. A successful response that is not a JSON object raises APIResponseError, which has a status attribute. A JSON object is not otherwise schema-validated.

HTTPX transport errors, including httpx.TimeoutException and other httpx.RequestError exceptions, propagate unchanged. The SDK does not wrap them in APIError.

Default 429 waits are 0.5 then 1 second. Retry-After accepts seconds or an HTTP date; the client waits at least the larger of that value and the backoff. Invalid or non-finite headers fall back to backoff, and past dates are treated as zero. If the server requests more than max_retry_delay, the SDK raises the 429 immediately rather than retrying too early.

No automatic retries occur for network failures, timeouts, 5xx responses, or malformed successful responses. Do not add blind retries around billed calls, including billable GET requests: the server may have charged credits before a response was lost. Inspect balance/history and the failure before deciding whether another request is appropriate.

Credits and rate limits

  • Cached transcript: 0 credits. New transcript: 1 credit, or 2 when the video exceeds 2 hours. Maximum duration: 4 hours.
  • Every summary: 1 separate additional credit, including a summary of a cached transcript. Web-app first-summary inclusion does not apply to REST SDK calls.
  • Search, channel search, channel videos, playlist videos, and comments: 1 credit per requested page.
  • Credit balance, channel resolution, and channel latest: free.

API access is available on the Free plan. Request limits are Free: 10/minute, Plus: 10/minute, Pro: 50/minute, and Scale: 300/minute. A free endpoint still makes an API request. Use returned credits_used values where present and credits()["balance"] for accounting.

Related resources

Start free
5 credits · 1 more every day · no card
Start free