Open-source project
claudiob/yt avatar
claudiob/yt

Yt, a Ruby client for the YouTube Data and Analytics APIs

The reliable YouTube API Ruby client

758 stars163 forksRubyMIT

At a glance

What is it?
claudiob/yt gives Ruby applications a model layer over the YouTube API, covering channels, videos, playlists, comment threads and the content owner analytics endpoints, with an active record style interface where each object exposes its associations as collections you can query. It is MIT licensed and installed as a gem.
Who is it for?
Adopt Yt if you are building a Ruby or Rails tool that reads YouTube data and want the resources modelled as objects with association collections rather than raw JSON. Skip it if you need only one endpoint and can call the REST API directly, since the gem adds a layer you then have to understand.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 22 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the gem actually wraps

Yt is a Ruby client for the YouTube API, described as helping you write apps that need to interact with YouTube. The source is on GitHub and the documentation is on RubyDoc.

The shape of the library is a model layer over the API rather than a thin HTTP wrapper. A channel is an object, a video is an object, and each one exposes its associations as collections you can query with methods like where and map. From the README's example:

ruby
channel = Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow'
channel.title #=> "Fullscreen"
channel.public? #=> true
channel.videos.count #=> 12

The video example shows the same idea with pagination handled for you:

ruby
video = Yt::Video.new id: 'jNQXAC9IVRw'
video.title #=> "Fullscreen Creator Platform"
video.comment_count #=> 308
video.hd? #=> true
video.annotations.count #=> 1
video.comment_threads #=> #<Yt::Collections::CommentThreads ...>
# Use #take to limit the number of pages need to fetch from server
video.comment_threads.take(99).map(&:author_display_name) #=> ["Paul", "Tommy", ...]

The take method is the detail that matters for anyone using this in production. Comment threads are paginated, and a naive count or map over the collection would fetch every page, which for a video with tens of thousands of comments means tens of thousands of API requests and a quota exhaustion. take limits how many pages are pulled, and the README calls it out explicitly.

The resource list is broad. There are classes for Account, ContentOwner, Channel, Video, Playlist, PlaylistItem, CommentThread, Comment, BulkReportJob and BulkReport, plus collections for Videos and the other associated resources. The README points at per-resource pages on the project documentation site for the method lists, with RubyDoc as the detailed reference.

The repository layout is a conventional gem: lib/ for the code, spec/ for the RSpec tests with a.rspec file, a yt.gemspec, a Gemfile, CHANGELOG.md, a bin/ directory, and a YOUTUBE_IT.md file that appears to record the YouTube integration test setup. The licence is MIT.

Installation and version pinning

Installing is a standard gem install:

bash
gem install yt

For a bundled project the README says to add the gem to the Gemfile, with a version constraint:

ruby
gem 'yt', '~> 0.34.0'

The constraint is described as pinning the full version in the major.minor.patch form, and the reason given is that since the gem follows Semantic Versioning, doing so guarantees that your project will not break when you run bundle update and a new version of Yt is released.

That reasoning is worth a small challenge, because it is slightly off. The pessimistic constraint operator with three segments pins to patch versions within the minor, which does protect against a breaking change arriving in a minor bump. It also means you miss every patch release until you edit the Gemfile, which is the other side of the trade.

The current version at 0.34.x also tells you something about the state of the API. A zero major version under semantic versioning means anything may change, and the fact that the gem is still on 0.x says more about the rate of upstream change than about the quality of the library.

The dependency picture implied by the README is OAuth 2 based. The topics list includes oauth2 and rails, and the content owner section shows the three ways a content owner can be initialised: with an access token, a refresh token or an authorization code. The install and configuration section of the README is not included in the documentation available here, so the exact steps for registering an app and completing the OAuth flow are the first thing to check in the project's own documentation.

For a Rails application, the gem would be used from a background job or a console rather than from a request cycle, since every association load is a network call to the YouTube API.

The content owner and analytics side

The ContentOwner class covers the part of the API that most client libraries leave out, which is the YouTube Analytics and content owner management surface.

From the README, the class lets you authenticate as a YouTube content owner, list the channels partnered with that owner, list the claims administered by the owner, list and delete the references administered by it, list policies and policy rules, create assets, and list assets.

The example shows how much of the API this is:

ruby
content_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'

content_owner.partnered_channels.count #=> 12
content_owner.partnered_channels.map &:title #=> ["Fullscreen", "Best of Fullscreen", ...]
content_owner.partnered_channels.where(part: 'statistics').map &:subscriber_count #=> [136925, 56945, ...]

Note the where part on the association. That is how you ask the API for a specific part of the resource rather than fetching everything, which is both a quota saving and the difference between a usable client and an unusable one on a large channel.

Claims are the other half. A claim is the link between a content owner and a video, and the API exposes their status and video id:

ruby
content_owner.claims.where(q: 'Fullscreen').count #=> 24
content_owner.claims.first #=> #<Yt::Models::Claim @id=...>
content_owner.claims.first.video_id #=> 'jNQXAC9IVRw'
content_owner.claims.first.status #=> "active"

Policies and rules are the monetisation configuration, and the model follows the API structure down to the territories a rule applies to:

ruby
content_owner.policies.first.name #=> "Track in all countries"
content_owner.policies.first.rules.first.action #=> "monetize"
content_owner.policies.first.rules.first.included_territories #=> ["US", "CA"]

The bulk report classes are the Analytics side. A BulkReportJob has a report type id, and the reports it produced have a start time, an end time and a download URL pointing at the reporting API.

All of these methods, the README notes, require authentication. That is the practical difference between the read-only part of the API, where a channel or video can be fetched by id with no credentials, and the write-capable content owner surface.

Collections, lazy loading and how the model layer behaves

The part of the gem worth understanding before you rely on it is how the collections behave, because that determines both your quota usage and your error handling.

The collections are the reason the gem is more than a set of hash wrappers. A video exposes comment_threads, annotations and a comment_count; a channel exposes videos, playlists and a subscriber count. Each of those is an object that queries the API when it is asked for data, and the where method on a collection passes parameters straight through to the API, which is why the content owner example can ask for statistics on one part of a resource.

Three behaviours follow from that design and each one catches people out at least once.

First, an association load is a network call. Nothing is cached by default, so calling video.comment_threads twice queries YouTube twice. In a Rails view that means an N plus one query pattern that will exhaust the quota on a list page.

Second, pagination is lazy and unbounded unless you bound it. The take method is the answer, and the README is explicit that it exists to limit the number of pages fetched from the server. For a video with fifty thousand comments, iterating the whole collection is tens of thousands of requests.

Third, errors surface as exceptions from a method call rather than as a returned value. That is idiomatic Ruby and works well in a background job where you can rescue and retry. It means a request inside a template raises rather than rendering a partial, so the safe usage is to load what you need in a controlled place.

The counts are the cheap alternative. comment_count and hd? in the README example are attributes on the video object rather than associations, which means they come from the video resource itself in one request instead of a separate listing. When you only need a number, asking the parent resource for it is both faster and cheaper.

The model layer also gives you a consistent way to work with resources that the API exposes under different names. The YouTube API returns video lists as items under a videos key and playlist items under a snippet key, and a client that exposes those raw shapes makes every caller deal with the difference. The gem normalises that, which is the quiet value that keeps appearing when you compare it with a hand-rolled parser.

Where Yt fits against the alternatives

The obvious alternative is calling the REST API directly with Faraday or httparty and parsing the JSON yourself. For one or two endpoints that is a few lines, and it has the advantage that a change in the YouTube API cannot break you, because there is no model layer to update.

The difference in approach is that Yt models the API as objects with associations, the way an active record library models a database. That buys you three things. The YouTube API is spread over several related resources with different shapes and different auth requirements, and the gem flattens that into one consistent interface where a channel, a video and a comment thread all behave the same way. It handles pagination, which is the single most common way to write a broken YouTube client. And it names things the way the API documents them, so the RubyDoc is a usable reference rather than a set of JSON schemas.

The cost is a dependency on someone else's model of a third-party API. When YouTube adds a parameter or changes a field, the gem has to be updated, and until it is you work around it. Given that the YouTube API changes regularly and the gem is a 0.x release, that is not a hypothetical.

There is also the official Google API client for Ruby and the hand-rolled HTTP approach. The generated client gives you guaranteed coverage of the API at the cost of a dynamic, low-level interface. Yt gives you a small, readable surface at the cost of lagging coverage.

For a tool that reads channels, videos and comments, which is what most people build, Yt's trade is a reasonable one. For a tool that needs a single rarely-used endpoint, the direct call is simpler.

Editorial conclusion

Adopt Yt if you are building a Ruby or Rails tool that reads YouTube data and want the resources modelled as objects with association collections rather than raw JSON. Skip it if you need only one endpoint and can call the REST API directly, since the gem adds a layer you then have to understand. Verify first by installing the gem, creating a Yt::Channel with an id, and confirming that the association collections load lazily and that the requests stay within the quota you expect.

Frequently asked questions

How do I install the Yt gem?

Run gem install yt for a system install, or add gem 'yt', '~> 0.34.0' to the Gemfile for a bundled project. The README notes the gem follows Semantic Versioning, so pinning the full version in the Gemfile protects against a breaking change in a minor release.

What resources does the Yt gem cover?

Account, ContentOwner, Channel, Video, Playlist, PlaylistItem, CommentThread, Comment, BulkReportJob and BulkReport, plus collection classes for the associated resources such as Yt::Collections::Videos and Yt::Collections::CommentThreads.

How do I avoid exhausting the YouTube API quota when listing comments?

Comment threads are paginated, so use the take method on the collection to limit how many pages are fetched from the server. The README's example uses video.comment_threads.take(99) rather than iterating the whole collection.

What can Yt::ContentOwner do?

It authenticates as a YouTube content owner, lists partnered channels, claims, references, policies and policy rules, creates assets and lists assets. All of those methods require authentication, and the class can be initialised with an access token, a refresh token or an authorization code.

Is Yt maintained?

The repository is not archived and the last push was on 2026-10-01. The gem version is on the 0.x line at 0.34, which under Semantic Versioning means the interface may still change, and there are no GitHub releases, so the changelog and the gem version are the version record.

Official sources

  1. claudiob/yt on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/claudiob-yt.svg)](https://hysenlabs.com/projects/claudiob-yt)

Was this useful?