API reference
Reference for the Promise client, Effect provider, options, domain models, lower-level services, and tagged errors.
All examples import from the package root:
import { YouTube } from 'just-yt';Promise client
new YouTube(options?)
Creates a client without doing I/O. The first operation initializes one shared
Innertube session. See configuration for YouTubeOptions.
search(query, options?)
search(query: string, options?: SearchOptions): Promise<SearchPage>Returns one page by default. limit follows continuations until that many
results have been collected or the feed ends.
interface SearchOptions {
limit?: number;
continuation?: string;
type?: 'video' | 'channel' | 'playlist' | 'movie' | 'short';
uploadDate?: 'any' | 'hour' | 'today' | 'week' | 'month' | 'year';
duration?: 'any' | 'short' | 'medium' | 'long';
sortBy?: 'relevance' | 'rating' | 'upload_date' | 'view_count';
features?: readonly SearchFeature[];
}SearchFeature is 'hd' | 'subtitles' | 'creative_commons' | '3d' | 'live' | 'purchased' | '4k' | '360' | 'location' | 'hdr' | 'vr180'.
suggestions(query)
suggestions(query: string): Promise<readonly string[]>Returns YouTube autocomplete suggestions for a partial query.
video(target, options?)
video(target: string, options?: VideoOptions): Promise<VideoDetails>
interface VideoOptions {
basic?: boolean;
client?: ClientType;
}target can be a video ID or a watch, youtu.be, shorts, embed, or
live URL. basic: true skips enrichment from /next, which can omit like
count, comment count, subscriber count, and channel avatar.
videos(targets, options?)
videos(
targets: readonly string[],
options?: VideosOptions,
): Promise<readonly BatchResult<VideoDetails>[]>
interface VideosOptions extends VideoOptions, BatchOptions {}Processes several video IDs or URLs with bounded concurrency. Results have the
same order and length as targets; one failed video does not reject or cancel
the other lookups.
transcript(target, options?)
transcript(target: string, options?: TranscriptOptions): Promise<Transcript>
transcript(
target: string,
options: SegmentedTranscriptOptions,
): Promise<SegmentedTranscript>
interface TranscriptOptions {
language?: string;
client?: ClientType;
segmented?: false;
}
interface SegmentedTranscriptOptions {
language?: string;
client?: ClientType;
segmented: true;
}language matches a caption track by language code or displayed name. Without
it, the SDK prefers a human-written track and then an auto-generated track.
The default result contains the complete transcript as one whitespace-normalized
paragraph. Set segmented: true to receive timestamped segments instead. Both
modes remove caption line breaks and YouTube’s >> speaker markers.
transcripts(targets, options?)
transcripts(
targets: readonly string[],
options?: TranscriptsOptions,
): Promise<readonly BatchResult<Transcript>[]>
transcripts(
targets: readonly string[],
options: SegmentedTranscriptsOptions,
): Promise<readonly BatchResult<SegmentedTranscript>[]>
interface TranscriptsOptions extends TranscriptOptions, BatchOptions {}
interface SegmentedTranscriptsOptions
extends SegmentedTranscriptOptions, BatchOptions {}Processes several transcripts while capturing missing captions and other target-specific failures on the corresponding result item.
recommended(options?)
recommended(options?: RecommendedOptions): Promise<RecommendedFeed>
interface RecommendedOptions extends BatchOptions {
videos?: readonly VideoSeed[];
queries?: readonly QuerySeed[];
channels?: readonly ChannelSeed[];
limit?: number;
maxPerChannel?: number;
}
type VideoSeed = string | { video: string; weight?: number };
type QuerySeed = string | { query: string; weight?: number };
type ChannelSeed = string | { channel: string; weight?: number };Builds a feed from the seeds supplied. Every seed kind is optional; a bare
string is shorthand for a weight of 1. limit defaults to 50 and
maxPerChannel to 3.
A seed that fails is reported in skipped rather than rejecting the call. Seed
videos never appear among the results.
channel(target)
channel(target: string): Promise<ChannelDetails>Accepts a channel ID beginning with UC, an @handle, or a channel URL.
channels(targets, options?)
channels(
targets: readonly string[],
options?: ChannelsOptions,
): Promise<readonly BatchResult<ChannelDetails>[]>
interface ChannelsOptions extends BatchOptions {}Processes several channel IDs, handles, or URLs with ordered, per-target results.
Bulk options and results
All plural lookup methods default to two active targets. Concurrency is the
number of complete target operations in flight, not a division into fixed-size
batches. It can be lowered to 1 or raised as high as 4.
interface BatchOptions {
concurrency?: 1 | 2 | 3 | 4;
}
type BatchResult<T> =
| { ok: true; target: string; value: T }
| { ok: false; target: string; error: YouTubeError };As soon as one target finishes, the next target starts in its place. Expected lookup errors—including unavailable resources, exhausted network retries, and extraction failures—are returned on the affected item. The overall operation can still fail when its shared infrastructure cannot run, such as when session initialization fails.
close()
close(): Promise<void>Disposes the client’s managed runtime.
Search models
interface SearchPage {
results: readonly SearchResult[];
estimatedResults?: number;
continuation?: string;
}
type SearchResult =
| VideoSearchResult
| ChannelSearchResult
| PlaylistSearchResult;All results have a type discriminator, id, title, url, and thumbnails.
| Type | Notable fields |
|---|---|
VideoSearchResult |
type: 'video', description?, durationSeconds?, durationText?, author?, publishedText?, viewCount?, isLive, badges |
ChannelSearchResult |
type: 'channel', handle?, description?, subscriberCount?, videoCountText?, isVerified |
PlaylistSearchResult |
type: 'playlist', videoCount?, author? |
Video model
interface VideoDetails {
id: string;
title: string;
url: string;
description?: string;
durationSeconds?: number;
thumbnails: readonly Thumbnail[];
channel: AuthorRef & {
subscriberCount?: number;
subscriberCountText?: string;
};
viewCount?: number;
likeCount?: number;
commentCount?: number;
publishedAt?: string;
uploadedAt?: string;
publishedText?: string;
category?: string;
keywords: readonly string[];
isLive: boolean;
isLiveContent: boolean;
isUpcoming: boolean;
isPrivate: boolean;
isUnlisted: boolean;
isFamilySafe?: boolean;
allowRatings?: boolean;
captions: readonly CaptionTrack[];
availableCountries: readonly string[];
playabilityStatus: string;
playabilityReason?: string;
}Dates are strings, not Date objects. Optional numeric fields mean “YouTube did
not supply this value,” not zero.
Transcript model
interface Transcript {
title: string;
data: string;
}
interface SegmentedTranscript {
title: string;
data: readonly TranscriptSegment[];
}
interface TranscriptSegment {
start: number;
end: number;
text: string;
}
interface CaptionTrack {
languageCode: string;
name?: string;
isAutoGenerated: boolean;
isTranslatable: boolean;
}The default data joins cleaned caption segments with a blank line between
them. Segmented start and end values are measured in seconds. Segment text
is normalized to one line, and neither mode includes YouTube’s >> speaker
markers.
Channel model
interface ChannelDetails {
id: string;
title: string;
handle?: string;
url: string;
canonicalUrl?: string;
description?: string;
thumbnails: readonly Thumbnail[];
banner: readonly Thumbnail[];
subscriberCount?: number;
subscriberCountText?: string;
videoCount?: number;
videoCountText?: string;
viewCount?: number;
viewCountText?: string;
joinedDateText?: string;
country?: string;
keywords: readonly string[];
tags: readonly string[];
links: readonly ChannelLink[];
isFamilySafe?: boolean;
isVerified: boolean;
}Recommended feed model
Feed entries are preview cards. They carry what a listing renderer provides and
nothing more — resolve an id with video() for full metadata.
interface RecommendedFeed {
items: readonly FeedItem[];
skipped: readonly SkippedSeed[];
}
interface FeedItem {
id: string;
title: string;
url: string;
thumbnails: readonly Thumbnail[];
author?: AuthorRef;
durationSeconds?: number;
durationText?: string;
viewCount?: number;
viewCountText?: string;
publishedText?: string;
isLive: boolean;
sources: readonly FeedItemSource[];
score: number;
}
interface FeedItemSource {
seed: string;
kind: 'video' | 'query' | 'channel';
via: 'mix' | 'related' | 'uploads' | 'search';
}
interface SkippedSeed {
seed: string;
kind: 'video' | 'query' | 'channel';
reason: string;
}score orders items within one feed and is not comparable between feeds. More
than one entry in sources means separate seeds agreed on the item, which is
what raises its score.
Shared models
interface Thumbnail {
url: string;
width?: number;
height?: number;
}
interface AuthorRef {
id?: string;
name?: string;
handle?: string;
url?: string;
thumbnails: readonly Thumbnail[];
isVerified: boolean;
}
interface ChannelLink {
title?: string;
url?: string;
}Errors
Errors are exported classes with a literal _tag. They do not share a runtime
base class; JustYtError is their TypeScript union, and YouTubeError is the
high-level operation error union.
Class / _tag |
Important fields | Meaning |
|---|---|---|
NetworkError |
message, url, cause? |
The request did not reach YouTube or its response could not be read. |
SessionError |
message, cause? |
The anonymous Innertube session could not be established. |
InnertubeError |
message, endpoint, status, body? |
YouTube returned a non-2xx response. |
ExtractionError |
message, path, received? |
The response shape did not match the parser. |
NotFoundError |
message, kind, id |
A video, channel, playlist, or transcript could not be found. |
UnavailableError |
message, videoId, status, reason? |
A known video is not playable by the anonymous client. |
import { NotFoundError, UnavailableError } from 'just-yt';
try {
await yt.video(id);
} catch (error) {
if (error instanceof NotFoundError) return undefined;
if (error instanceof UnavailableError) {
console.warn(error.status, error.reason);
return undefined;
}
throw error;
}Effect API and provider
YouTubeApi is an Effect context tag with the same operations. It also adds
searchStream, which returns Stream.Stream<SearchResult, YouTubeError>.
import { Effect } from 'effect';
import { YouTubeApi, layer } from 'just-yt';
const program = Effect.gen(function* () {
const yt = yield* YouTubeApi;
return yield* yt.channel('@veritasium');
});
await Effect.runPromise(program.pipe(Effect.provide(layer())));layer(options?) provides the complete YouTubeStack: Config, Session,
Innertube, and YouTubeApi. Build and share the layer instead of recreating it
for each request.
Lower-level exports
| Export | Purpose |
|---|---|
Config, Config.layer, resolveConfig |
Resolve options into runtime configuration. |
Session, SessionLive, makeSession |
Create and access anonymous session state. |
Innertube, InnertubeLive |
Execute a raw Innertube endpoint. |
CLIENTS, CLIENT_TYPES, CLIENT_NAME_IDS |
Predefined YouTube request profiles and identifiers. |
URLS |
YouTube service URLs used internally. |
parseVideoId, parseChannelTarget |
Parse accepted IDs and URLs. |
Raw Innertube data is intentionally unknown and unstable. Prefer the
high-level models whenever the SDK wraps the endpoint.