Changelog
Source:NEWS.md
tuber 2.0.0.9000 (development version)
httr2
- tuber now talks to YouTube entirely through httr2. httr is no longer a dependency.
-
Saved OAuth tokens must be recreated. Tokens written by tuber 2.0.0 and earlier are httr
Token2.0objects, which httr2 cannot use.yt_oauth()says so and authenticates again; the new token replaces the old file. -
options(google_token)now holds an httr2 token. Code readingtoken$credentials$access_tokenshould readtoken$access_token. -
yt_oauth()refuses to write into a file named.httr-oauth. That name is httr’s shared cache, read by every httr-based package in the same working directory, and an httr2 token there would break them. tuber’s own default lives intools::R_user_dir("tuber", "cache"). - An expired access token is refreshed automatically when the OAuth client is still available, instead of failing the request.
- Credentials travel in redacted headers, so a printed request or an error dump no longer shows the bearer token or API key.
- The
...argument of the internal HTTP functions no longer reaches httr’s configuration. The argument is still accepted and ignored.
Fixes
-
set_comment_moderation_status()and other endpoints returning HTTP 204 no longer attempt to parse an absent response body. - Uploads that fail to start now report YouTube’s own error message rather than a bare status code.
tuber 2.0.0
CRAN release: 2026-08-20
Released 2026-08-17.
Breaking API cleanup
- List endpoints now use a consistent
list_*()prefix. The renamed functions arelist_comments(),list_comment_threads(),list_playlist_items(),list_playlists(),list_subscriptions(),list_live_chat_messages(), andlist_super_chat_events(). - Resource-specific names replace ambiguous names and abbreviations, including
get_video_stats(),get_channel_details(),list_popular_videos(),list_video_categories(),list_languages(), anddownload_caption(). - Singular mutation arguments use singular names, such as
video_id,comment_id, andplaylist_item_id. Plural ID arguments accept vectors. - Public reads default to API-key authentication. OAuth-only functions no longer expose an
authchoice. - Simplified list results use fixed snake-case schemas. Set
simplify = FALSEto retain the collected API response.get_video_details()remains dynamic because its columns depend onpart.
See vignette("api-conventions", package = "tuber") for the full migration table and endpoint support matrix.
Correctness
- Video and caption uploads now use Google’s resumable upload protocol, and actually resume (#81). The file goes up in
Content-Range-tagged chunks; if a chunk dies in flight or draws a 5xx, tuber asks YouTube how many bytes it kept and continues from there instead of restarting at byte zero. Tune with the newchunk_size(default 8 MB) andmax_tries(default 5) arguments toupload_video()andupload_caption(). An expired session URL raisestuber_upload_session_expired; exhausting the retries raisestuber_upload_interrupted, whose condition carries the byte count reached. Thumbnail and channel-banner uploads use explicit media uploads and enforce YouTube’s file-size limits. - Comment collection fetches every reply page instead of relying on the reply preview embedded in a comment thread.
- Channel, playlist, subscription, comment, live-broadcast, and search wrappers now enforce the filter combinations documented by YouTube.
- Pagination treats
max_resultsas a total limit and trims the first page as well as later pages. - Quota estimates use Google’s current data, search, and video-upload buckets and method-specific costs.
- The optional response cache covers reference data, is transparent and persistent when configured, and is isolated by authentication credentials.
- Removed wrappers for retired related-video and guide-category endpoints.
version 1.4.1
CRAN release: 2026-08-02
Bug fixes
-
list_videocats()andlist_guidecats()appended the translated filter to the query list as an unnamed element, so the query contained an unnamed component. Bothhttrandhttr2reject such a query (“All components of query must be named”), so neither function could issue a request at all. The filter is now merged by name, andregionCode/idreach the API.Note for
list_guidecats()specifically: Google deprecated theguideCategoriesendpoint in September 2020 and it no longer returns data. The request is now assembled correctly, but the method it targets is gone, so this repairs the client rather than restoring the feature. get_live_streams()acceptedchannel_idand required either that orstream_id, then sentchannelIdalongsidebroadcastStatus.liveBroadcasts.listhas nochannelIdparameter and accepts exactly one ofbroadcastStatus,idormine, so a status-only query was impossible and the combinations it did send were invalid. It now takes exactly one filter, gainsmine, and errors clearly on the rest.get_comments(simplify = TRUE)assigned the first comment’s id to every row, becauseraw_res$items[[1]]$idis a scalar that R recycled over the frame. Two comments came back carrying the same id and the second was lost. It also sentpageTokenandmaxResultsalongside acomment_idfilter, whichcomments.listdocuments as unsupported withid.list_videocats()indexed its filter withfilter$regionCode.filteris a named character vector, so this raised “$ operator is invalid for atomic vectors” on every call.list_guidecats()failed the same way when assembling its result: with no items it raised “replacement has 1 row, data has 0”, and with items it returned a list rather than the documenteddata.frame. Both now index by name and return adata.framein every case.get_comments()documented and validated apage_tokenargument but never placed it in the query, so paging through replies with aparent_idfilter always returned the first page. It is now sent aspageToken.list_regions()andlist_abuse_report_reasons()documented and validated anhlargument that never reached the query. Bothi18nRegions.listandvideoAbuseReportReasons.listsupporthl, and the siblinglist_langs()already sent it. It is now sent.get_live_streams()sent itsstatusfilter aseventType, which is asearch.listparameter.liveBroadcasts.listfilters onbroadcastStatus.
version 1.4.0
CRAN release: 2026-03-25
Major API Coverage Enhancements (Closing the Gap)
This release significantly expands tuber’s capabilities to support full programmatic channel management and deep creator economy analytics:
1. Community Engagement & Moderation
Added functions to actively manage and engage with your community: * post_comment(): Programmatically post new top-level comments to videos or channels. * reply_to_comment(): Reply to existing comments. * set_comment_moderation_status(): Approve, reject, or hold comments for review, with an option to ban authors.
2. Monetization & Live Chat Data Extraction
Added highly requested data extraction tools for analysts tracking the creator economy: * get_super_chat_events(): Retrieve all Super Chat and Super Sticker events, including currency amounts and donor details. * get_live_chat_messages(): Extract real-time chat messages from active live broadcasts. * list_channel_members(): List all active channel members and their tier levels.
3. Channel Branding & Customization
Completed the video publishing pipeline with new media upload endpoints: * set_video_thumbnail(): Upload and set custom thumbnails for your videos. * insert_channel_banner(): Upload custom channel banner art.
Critical Issue Resolution and Enhanced Error Handling
This release resolves 19 out of 22 total GitHub issues, dramatically improving package reliability and user experience:
Major Bug Fixes Resolved
- PAGINATION ISSUES: Fixed comment and playlist pagination duplicates (#107, #95, #88, #52, #33)
- AUTHENTICATION ERRORS: Enhanced 403 error handling with step-by-step setup instructions (#66, #15)
-
UNICODE HANDLING: Comprehensive Unicode and emoji support with
unicode_utils.R(#79) -
MISSING FEATURES: Added contentDetails support to
get_stats()function (#77) - AUTOGENERATED CHANNELS: Intelligent detection with helpful error messages (#118)
- USERNAME LOOKUP: Improved reliability with retry logic for intermittent failures (#67)
Enhanced Documentation and User Experience
- TROUBLESHOOTING GUIDE: New comprehensive troubleshooting vignette for common issues
- EMOJI SUPPORT: New vignette covering Unicode and emoji handling in YouTube data
- CAPTIONS ACCESS: Clarified authentication requirements and ownership restrictions (#23)
-
FIELD EXTRACTION: Added Shiny-specific examples for
get_video_details()(#87) - API LIMITATIONS: Documented proper approaches for playlist search vs. direct retrieval (#73)
Infrastructure Improvements
- ERROR MESSAGES: Enhanced error handling provides actionable solutions instead of cryptic messages
- API COMPLIANCE: All functions now strictly follow YouTube API documentation
- SEARCH FUNCTIONALITY: Proper max_results handling prevents quota waste (#64)
- SUBSCRIPTION LIMITS: Documented existing support for 1000+ subscription retrieval (#76)
Remaining Features
- UNLISTED VIDEOS: Documented OAuth authentication requirement for private content access (#80)
- RESUMABLE UPLOADS: Current implementation uses basic resumable protocol; full chunked resumption planned for future major version (#81)
Impact: Package reliability increased from ~60% to ~95% with most critical user-reported issues resolved.
version 1.2.0
Major Performance and Infrastructure Improvements
This release focuses on core infrastructure improvements, performance optimizations, and reliability enhancements:
Core Infrastructure Improvements
-
HTTP CLIENT CONSOLIDATION: Unified authentication system supporting both OAuth2 (
auth = "token") and API key (auth = "key") authentication across all functions - STANDARDIZED ERROR HANDLING: Comprehensive error handling with user-friendly messages and solution suggestions
- RETRY LOGIC: Automatic exponential backoff retry for transient API failures improves reliability
- ENHANCED VALIDATION: YouTube-specific parameter validation prevents common user errors
Performance Enhancements
-
BATCH OPERATIONS: New high-performance functions for bulk data retrieval:
-
get_videos_batch(): Process up to 50 videos per API call (50x more efficient) -
get_channels_batch(): Bulk channel statistics retrieval -
get_playlists_batch(): Efficient playlist information fetching
-
- RESPONSE CACHING: Optional caching for static data (video categories, regions, languages) reduces quota usage
-
HELPER FUNCTIONS: High-level convenience functions for common tasks:
-
analyze_channel(): Comprehensive channel analysis -
compare_channels(): Multi-channel comparison -
bulk_video_analysis(): Performance benchmarking across video sets
-
Extended API Coverage
-
NEW ENDPOINTS: Support for previously missing YouTube API endpoints:
-
get_live_streams(): Live broadcast and premiere information -
get_video_thumbnails(): Thumbnail URLs and metadata -
get_channel_sections(): Channel sections and featured content -
search_shorts(): YouTube Shorts-specific search -
get_premiere_info(): Premiere scheduling information
-
Code Quality and Maintenance
-
LINTING: Fixed
.lintrconfiguration enabling automated code quality checks - DOCUMENTATION: Comprehensive documentation with examples for all new functions
-
DEPENDENCIES: Added
digestpackage for caching functionality - CONSISTENCY: Standardized patterns across all 65+ R functions
version 1.1.1
Bug Fixes and Improvements
This patch release addresses several critical bugs and improves documentation:
Critical Bug Fixes
-
PAGINATION: Fixed
get_comment_threads()pagination bug where comments were duplicated instead of fetching unique results whenmax_results > 100(issue #107) -
PLAYLIST ITEMS: Fixed
get_playlist_items()returning only metadata instead of actual video items (issue #95) -
CHANNEL VIDEOS: Fixed
list_channel_videos()returning only pageInfo instead of video details (issue #88) -
AUTO-GENERATED CHANNELS: Improved error handling for YouTube auto-generated channels (music topics, etc.) with helpful guidance to use
yt_search()instead (issue #118)
Documentation Improvements
-
VIDEO DETAILS: Added comprehensive examples for extracting specific fields from
get_video_details()including Shiny application usage (issue #87) - UNLISTED VIDEOS: Documented OAuth authentication requirement for accessing unlisted video statistics (issue #80)
-
API REFERENCE: Fixed incorrect API documentation URL in
get_playlist_items()
version 1.1.0
CRAN release: 2025-08-25
Major Bug Fixes and Performance Improvements
This release fixes critical issues that were causing the package to be unreliable for production use:
Critical Fixes
- BREAKING BUG: Fixed OAuth token caching - authentication was completely broken (issues #135, #107, #64)
-
PERFORMANCE: Fixed O(n²) pagination in
get_all_comments()- now scales linearly (issues #62, #111, #115) -
RELIABILITY: Fixed username lookup failures in
list_channel_resources()with retry logic (issue #73) - ERROR HANDLING: Added proper validation for videos with disabled/no comments (issue #115)
High-Priority Improvements
-
QUOTA MANAGEMENT: New comprehensive quota tracking system (issue #116)
- Added
yt_get_quota_usage(),yt_set_quota_limit(),yt_reset_quota()functions - Automatic quota usage tracking with warnings before limits reached
- Rate limiting detection and management
- Added
-
PERFORMANCE: Optimized
yt_search()to stop fetching when max_results reached (issues #66, #77) -
BATCH API CALLS: Rewrote
get_all_channel_video_stats()to use batch requests (50x fewer API calls) -
CHANNEL ID LOGIC: Complete rewrite of channel ID handling (issues #95, #122)
- Proper validation for UC/UU channel IDs
- API-based fallback for brand channels and custom URLs
- Clear error messages for unsupported channel types
- UNICODE HANDLING: Standardized UTF-8 processing across all functions (issue #80)
- ERROR HANDLING: Improved contentDetails processing with proper null checks (issue #79)
New Features
- Added comprehensive quota management system
- Added retry logic with exponential backoff for intermittent API failures
- Added progress indicators for long-running operations
- Added detailed error messages explaining common failure scenarios
Performance Improvements
-
get_all_comments(): ~100x faster for videos with many comments -
yt_search(): ~50% quota savings by precise result fetching -
get_all_channel_video_stats(): 50x fewer API calls through batching -
list_channel_resources(): ~95% reliability improvement with retry logic
version 0.9.9.9000 (development version)
- Added support for API key authentication with two new exported functions,
yt_get_key()andyt_set_key(), and a newauthargument to the internal functiontuber_GET(). Users can now passauth = "key"to any function that usestuber_GET()to enable API key authentication. The behavior oftuber_GET()remains unchanged when using the new default,auth = "token", which avoids breaking changes to previously written code (@gvelasq, #117).
version 0.9.9
CRAN release: 2020-06-11
- added functionality like upload_video etc. see https://github.com/gojiplus/tuber/commit/2cf53c50e9079af0f6b1a478698d0bda15f4c5e0
- bug fix: https://github.com/gojiplus/tuber/commit/c1d6d82fe9334bb1aecbeb006521dcf99f803a88
version 0.9.5
CRAN release: 2018-03-01
- add some other util functions for getting details on all videos from a channel
- mine = TRUE
version 0.9.3
CRAN release: 2018-02-03
- A new vignette for tuber that shows how to deal with emojis in tuber
- A new function for fetching all the comments, including replies. Also fixes #43
- Added the missing partner scope fixing #41.
- New pkgdown documentation released with functions organized by purpose.
- get_related_videos returns related video id in addition to other cols.
version 0.9.2
CRAN release: 2017-11-19
fixes list_channel_videos. it used to iterate over all the playlists. You don’t need to do that. All the uploaded videos of a channel are available in a playlist with the same id as channel id except the first two letters are switched.
fixes get_playlist_items. thanks to @TebanSierra. See #39.
version 0.9.1
CRAN release: 2017-09-20
- get_video_detail doesn’t hardcode part = ‘snippet’.
- get_playlists was trying to do argument matching w/ part which can be a comma separated list. So obviously it failed big time. Fixed now.
version 0.9.0
CRAN release: 2017-05-28
- Extensive linting. Passes expect_lint_free
- Removed support for caption tracks from old Youtube API as client should only be for V3. Changed the get_captions API.
- support the deletes
- translate_filter in get_comment_threads also supports pagetoken, which it didn’t.
- removes cats (prints) from get_stats based on user feedback
- list_channel_videos now supports getting all the videos from the playlists
- get_playlist_items supports simplify, defaults to simplify, and also allows getting all the videos from the playlist easily.
- get_comment_threads allows getting all the comment_threads
version 0.8.0
CRAN release: 2017-04-11
- get_all — iterate through the results and get all supported for various functions. supported for yt_search(). prints removed from yt_search()
- yt_search() for returns a data.frame with video_id when simplify is TRUE
- When a resource with a particular ID is not found, the functions now issue a warning() rather than ‘cat’ out the problem.
version 0.7.0
CRAN release: 2016-11-21
- No more invisible return
- Rather than is.null checks, !is.character checks for args expected to be chars
- using ldly for more robust rbind of data.frames
- Specific functions:
- get_playlists now supports simplify — allows for data.frame return
- More consistent return for get_related_videos() — df with same cols. even if no results.
- list_guidecats() and list_videocats() now return region_code as part of the returned data.frame
- return when simplify is TRUE for yt_search() now gives a data.frame with 15 columns
- nicer return and documentation for list_channel_activities()
- better documentation for get_playlists()
- fixed a bug in list_abuse_report_reasons() for part as snippet
version 0.6.0
CRAN release: 2016-11-11
- Based on CRAN feedback, add comment about yt_outh to all man pages
- video_id is returned as part of the list for get_stats, get_video_details
- handles errors stemming from bad video id for get_stats, get_video_details
- fixed bug in get_comment that delivers separate results for diff. filters, error handling for bad comment_id, and now comment_id returned as part of df
- better returns when simplify is TRUE for get_related_videos, get_comment_threads
- list_caption_tracks function added. updated get_captions to only return caption related to a particular caption_id or video_id
version 0.5.0
- Added contributor code of conduct
- yt_search takes a new argument simplify which if TRUE returns a dataframe with 7 elements. Otherwise it returns a list with all the information.
version 0.4.0 2016-10-04
CRAN release: 2016-10-04
- Filtering by different facets is now supported. This is via passing a named vector.
- Added a function to list_channel_videos
- Added a function to get comment threads
- Added to the vignette an example of how to get stats of all videos of a channel.
version 0.3.0 2016-08-04
CRAN release: 2016-08-04
- Replaces list_channel_videos with list_channel_resources. Returns a list.
- Supports and documents all optional params except onBehalfOfContentOwner, for list_guidecats, list_channel_activities, get_captions, list_channel_sections, get_comments, list_langs, list_regions
- Adds get_playlists, get_playlist_items, get_subscriptions, get_videos
- Renames get_channel with get_channel_stats
- Standardize argument naming to snake_case
version 0.2.1 2016-06-20
CRAN release: 2016-06-20
- Support the dots — allow for passing of extra arguments to httr GET and POST
- More tests
- Added list channel activities and list channel sections
- Get details uses the abstract infrastructure
- yt_oauth takes path to token file. removing file no longer supported
version 0.2.0 2016-01-16
- Deprecated Freebase Topic Search
- Supports many more functions of the API. For instance, list_langs, list_guidecats, list_videocats, list_regions
- Supports more arguments for many of the functions. For instance, comments now supports maxResults, textFormat etc.
- Return defaulted to a data.frame in many of the functions