Graph discovery
Walk the graph linked from a video, channel, or playlist breadth-first with ytb discover: follow uploaders, related videos, uploads, playlists, items, owners, community posts, comments, and the channels behind them.
Every other read answers one question about one object: a video's metadata, a channel's uploads, a playlist's items.
ytb discover chains them.
It starts at a video, channel, or playlist and follows that object's links outward, hop by hop, streaming every node it reaches.
It is a breadth-first walk of the YouTube graph.
ytb discover dQw4w9WgXcQ # what is this video linked to?
ytb discover @MrBeast # what is this channel linked to?
A seed is any reference ytb already resolves: a video id or watch URL, a channel id, @handle, or URL, or a playlist id or URL.
Pass more than one to start the walk from several places at once.
What gets followed
The default follows an object's content: a video yields its uploader and related videos, a channel yields its uploads, a playlist yields its items and owner.
It spans every seed kind, so ytb discover <anything> does the obvious thing with no flags, and it stays on the open surface, so it needs nothing special.
Choose what to follow with --follow.
It takes a preset:
ytb discover <ref> --follow content # uploader, related, uploads, items, owner (default)
ytb discover <channel> --follow feed # uploads, playlists, community posts
ytb discover <video> --follow comments # comments and the channels that wrote them
ytb discover <ref> --follow all # every edge
or a comma-separated list of individual edges:
ytb discover <video> --follow channel,related
ytb discover <channel> --follow uploads,playlists
The full edge vocabulary:
| Edge | From → to | Gated | What it follows |
|---|---|---|---|
channel |
video → channel | no | the channel that uploaded the video |
related |
video → video | no | a related / recommended video |
comments |
video → comment | yes | a comment on the video |
uploads |
channel → video | no | a video the channel uploaded |
playlists |
channel → playlist | no | a playlist the channel owns |
community |
channel → post | no | a community-tab post |
items |
playlist → video | no | a video in the playlist |
owner |
playlist → channel | no | the channel that owns the playlist |
commenter |
comment → channel | yes | the channel that wrote the comment |
Name an edge directly to chase just that link: --follow related walks the recommendation graph, --follow uploads sweeps a channel.
YouTube serves the open surface to an anonymous request, so there are no tiers to add.
The only gated edges are the two that touch comments: YouTube applies a per-IP Restricted Mode to some networks, and when it refuses the comments, ytb discover notes it on stderr and keeps going on the rest of the graph rather than failing the walk.
So --follow all from a flagged network still returns the channel, related videos, playlists, and everything else, with one advisory about the comments it could not read.
How far and how wide
ytb discover <ref> --depth 2 # follow two hops from the seed (default 1)
ytb discover <ref> --fanout 50 # up to 50 neighbors per edge (default 25)
ytb discover <ref> --fanout 0 # no per-edge cap
ytb discover <ref> -n 1000 # stop after 1000 nodes total (default 500)
--depth is how many hops to follow; 0 emits only the seeds.
--fanout caps how many neighbors each edge contributes per node, so one hop never pages a whole upload history unless you raise it.
-n/--limit is the total node budget, the hard stop on a deep or wide walk; even --fanout 0 stays bounded by it, so a walk always terminates.
Reading the output
ytb discover streams one row per node, tagged with how it was reached:
depth via kind id who summary url
0 video dQw4w9WgXcQ RickAstley Never Gonna Give You U https://youtu.be/dQw4w9WgXcQ
1 channel channel UCuAXFkgsw1L RickAstley Rick Astley https://youtube.com/channel/UCuAXFkgsw1L
1 related video J---aiyznGQ ... Keyboard Cat https://youtu.be/J---aiyznGQ
Because it streams through the same formatter as every read, it shapes and pipes the same way. The JSON forms carry the full typed node, with the nested video, channel, playlist, comment, or post:
ytb discover <ref> -o json | jq -r '.via + " -> " + (.video.id // .channel.id)'
ytb discover @MrBeast --follow feed -o jsonl | jq -r '.video.id' | sort -u
ytb discover <ref> --fields depth,via,who,url -o table
Persisting a walk
Add --store to write every node the walk reached into the local store as it streams, so you keep the graph as well as see it:
ytb discover @MrBeast --follow all --depth 2 --store
ytb query "select kind, count(*) from nodes group by 1 order by 2 desc"
A node the walk fetched is stored with its record. A node it only saw in somebody else's shelf is stored as a sighting with a null record, because a title on a shelf is not a record and writing it down as one would say this video has no description and no likes. Re-walking is idempotent.
discover writes nodes and not claims.
The edge names above are how a person describes a hop, while a claim is made of the closed predicate vocabulary that ytb predicates prints, so ytb crawl is what writes the graph.
See the local store for the crawl, the query surface, and exporting what you collect.