{"id":50822484,"url":"https://github.com/teampiped/rustypipe","last_synced_at":"2026-06-13T15:04:12.593Z","repository":{"id":361355093,"uuid":"1253847147","full_name":"TeamPiped/rustypipe","owner":"TeamPiped","description":"Rust client for the public YouTube / YouTube Music API (Innertube)","archived":false,"fork":false,"pushed_at":"2026-06-08T18:39:21.000Z","size":12588,"stargazers_count":0,"open_issues_count":10,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T20:22:18.394Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TeamPiped.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-29T21:53:10.000Z","updated_at":"2026-05-31T11:50:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/TeamPiped/rustypipe","commit_stats":null,"previous_names":["teampiped/rustypipe"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/TeamPiped/rustypipe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TeamPiped%2Frustypipe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TeamPiped%2Frustypipe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TeamPiped%2Frustypipe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TeamPiped%2Frustypipe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TeamPiped","download_url":"https://codeload.github.com/TeamPiped/rustypipe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TeamPiped%2Frustypipe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34288669,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-13T15:04:11.760Z","updated_at":"2026-06-13T15:04:12.584Z","avatar_url":"https://github.com/TeamPiped.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![RustyPipe](https://codeberg.org/ThetaDev/rustypipe/raw/branch/main/notes/logo.svg)\n\n[![Current crates.io version](https://img.shields.io/crates/v/rustypipe.svg)](https://crates.io/crates/rustypipe)\n[![License](https://img.shields.io/badge/License-GPL--3-blue.svg?style=flat)](https://opensource.org/licenses/GPL-3.0)\n[![Docs](https://img.shields.io/docsrs/rustypipe/latest?style=flat)](https://docs.rs/rustypipe)\n[![CI status](https://codeberg.org/ThetaDev/rustypipe/actions/workflows/ci.yaml/badge.svg?style=flat\u0026label=CI)](https://codeberg.org/ThetaDev/rustypipe/actions/?workflow=ci.yaml)\n\nRustyPipe is a fully featured Rust client for the public YouTube / YouTube Music API\n(Innertube), inspired by [NewPipe](https://github.com/TeamNewPipe/NewPipeExtractor).\n\n## Features\n\n### YouTube\n\n- **Player** (video/audio streams, subtitles)\n- **VideoDetails** (metadata, comments, recommended videos)\n- **Playlist**\n- **Channel** (videos, shorts, livestreams, playlists, info, search)\n- **ChannelRSS**\n- **Search** (with filters)\n- **Search suggestions**\n- **Trending**\n- **URL resolver**\n- **Subscriptions**\n- **Playback history**\n\n### YouTube Music\n\n- **Playlist**\n- **Album**\n- **Artist**\n- **Search**\n- **Search suggestions**\n- **Radio**\n- **Track details** (lyrics, recommendations)\n- **Moods/Genres**\n- **Charts**\n- **New** (albums, music videos)\n- **Saved items**\n- **Playback history**\n\n## Getting started\n\nThe RustyPipe library works as follows: at first you have to instantiate a RustyPipe\nclient. You can either create it with default options or use the `RustyPipe::builder()`\nto customize it.\n\nFor fetching data you have to start with a new RustyPipe query object (`rp.query()`).\nThe query object holds options for an individual query (e.g. content language or\ncountry). You can adjust these options with setter methods. Finally call your query\nmethod to fetch the data you need.\n\nAll query methods are async, you need the tokio runtime to execute them.\n\n```rust ignore\nlet rp = RustyPipe::new();\nlet rp = RustyPipe::builder().storage_dir(\"/app/data\").build().unwrap();\nlet channel = rp.query().lang(Language::De).channel_videos(\"UCl2mFZoRqjw_ELax4Yisf6w\").await.unwrap();\n```\n\nHere are a few examples to get you started:\n\n### Cargo.toml\n\n```toml\n[dependencies]\nrustypipe = \"0.1.3\"\ntokio = { version = \"1.20.0\", features = [\"macros\", \"rt-multi-thread\"] }\n```\n\n### Watch a video\n\n```rust ignore\nuse std::process::Command;\n\nuse rustypipe::{client::RustyPipe, param::StreamFilter};\n\n#[tokio::main]\nasync fn main() {\n    // Create a client\n    let rp = RustyPipe::new();\n    // Fetch the player\n    let player = rp.query().player(\"pPvd8UxmSbQ\").await.unwrap();\n    // Select the best streams\n    let (video, audio) = player.select_video_audio_stream(\u0026StreamFilter::default());\n\n    // Open mpv player\n    let mut args = vec![video.expect(\"no video stream\").url.to_owned()];\n    if let Some(audio) = audio {\n        args.push(format!(\"--audio-file={}\", audio.url));\n    }\n    Command::new(\"mpv\").args(args).output().unwrap();\n}\n```\n\n### Get a playlist\n\n```rust ignore\nuse rustypipe::client::RustyPipe\n\n#[tokio::main]\nasync fn main() {\n    // Create a client\n    let rp = RustyPipe::new();\n    // Get the playlist\n    let playlist = rp\n        .query()\n        .playlist(\"PL2_OBreMn7FrsiSW0VDZjdq0xqUKkZYHT\")\n        .await\n        .unwrap();\n    // Get all items (maximum: 1000)\n    playlist.videos.extend_limit(rp.query(), 1000).await.unwrap();\n\n    println!(\"Name: {}\", playlist.name);\n    println!(\"Author: {}\", playlist.channel.unwrap().name);\n    println!(\"Last update: {}\", playlist.last_update.unwrap());\n\n    playlist\n        .videos\n        .items\n        .iter()\n        .for_each(|v| println!(\"[{}] {} ({}s)\", v.id, v.name, v.length));\n}\n```\n\n**Output:**\n\n```txt\nName: Homelab\nAuthor: Jeff Geerling\nLast update: 2023-05-04\n[cVWF3u-y-Zg] I put a computer in my computer (720s)\n[ecdm3oA-QdQ] 6-in-1: Build a 6-node Ceph cluster on this Mini ITX Motherboard (783s)\n[xvE4HNJZeIg] Scrapyard Server: Fastest all-SSD NAS! (733s)\n[RvnG-ywF6_s] Nanosecond clock sync with a Raspberry Pi (836s)\n[R2S2RMNv7OU] I made the Petabyte Raspberry Pi even faster! (572s)\n[FG--PtrDmw4] Hiding Macs in my Rack! (515s)\n...\n```\n\n### Get a channel\n\n```rust ignore\nuse rustypipe::client::RustyPipe\n\n#[tokio::main]\nasync fn main() {\n    // Create a client\n    let rp = RustyPipe::new();\n    // Get the channel\n    let channel = rp\n        .query()\n        .channel_videos(\"UCl2mFZoRqjw_ELax4Yisf6w\")\n        .await\n        .unwrap();\n\n    println!(\"Name: {}\", channel.name);\n    println!(\"Description: {}\", channel.description);\n    println!(\"Subscribers: {}\", channel.subscriber_count.unwrap());\n\n    channel\n        .content\n        .items\n        .iter()\n        .for_each(|v| println!(\"[{}] {} ({}s)\", v.id, v.name, v.length.unwrap()));\n}\n```\n\n**Output:**\n\n```txt\nName: Louis Rossmann\nDescription: I discuss random things of interest to me. (...)\nSubscribers: 1780000\n[qBHgJx_rb8E] Introducing Rossmann senior, a genuine fossil 😃 (122s)\n[TmV8eAtXc3s] Am I wrong about CompTIA? (592s)\n[CjOJJc1qzdY] How FUTO projects loosen Google's grip on your life! (588s)\n[0A10JtkkL9A] a private moment between a man and his kitten (522s)\n[zbHq5_1Cd5U] Is Texas mandating auto repair shops use OEM parts? SB1083 analysis \u0026 breakdown; tldr, no. (645s)\n[6Fv8bd9ICb4] Who owns this? (199s)\n...\n```\n\n## Crate features\n\nSome features of RustyPipe are gated behind features to avoid compiling unneeded\ndependencies.\n\n- `rss` Fetch a channel's RSS feed, which is faster than fetching the channel page\n- `userdata` Add functions to fetch YouTube user data (watch history, subscriptions,\n  music library)\n\nYou can also choose the TLS root certificate store used for making web requests using\nthe following features (`default-tls` / `rustls-tls-webpki-roots` for webpki roots,\n`rustls-tls-native-roots` for the OS certificate store). The legacy feature names\n`native-tls`, `native-tls-alpn`, and `native-tls-vendored` are aliases for\n`default-tls`.\n\n## Cache storage\n\nThe RustyPipe cache holds the current version numbers for all clients, the JavaScript\ncode used to deobfuscate video URLs and the authentication token/cookies. Never share\nthe contents of the cache if you are using authentication.\n\nBy default the cache is written to a JSON file named `rustypipe_cache.json` in the\ncurrent working directory. This path can be changed with the `storage_dir` option of the\nRustyPipeBuilder. The RustyPipe CLI stores its cache in the userdata folder. The full\npath on Linux is `~/.local/share/rustypipe/rustypipe_cache.json`.\n\nYou can integrate your own cache storage backend (e.g. database storage) by implementing\nthe `CacheStorage` trait.\n\n## Reports\n\nRustyPipe has a builtin error reporting system. If a YouTube response cannot be\ndeserialized or parsed, the original response data along with some request metadata is\nwritten to a JSON file in the folder `rustypipe_reports`, located in RustyPipe's storage\ndirectory (current folder by default, `~/.local/share/rustypipe` for the CLI).\n\nWhen submitting a bug report to the RustyPipe project, you can share this report to help\nresolve the issue.\n\nRustyPipe reports come in 3 severity levels:\n\n- DBG (no error occurred, report creation was enabled by the `RustyPipeQuery::report`\n  query option)\n- WRN (parts of the response could not be deserialized/parsed, response data may be\n  incomplete)\n- ERR (entire response could not be deserialized/parsed, RustyPipe returned an error)\n\n## PO tokens\n\nSince August 2024 YouTube requires PO tokens to access streams from web-based clients\n(Desktop, Mobile). Otherwise streams will return a 403 error.\n\nGenerating PO tokens requires a simulated browser environment, which would be too large\nto include in RustyPipe directly.\n\nTherefore, the PO token generation is handled by a seperate CLI application\n([rustypipe-botguard](https://codeberg.org/ThetaDev/rustypipe-botguard)) which is called\nby the RustyPipe crate. RustyPipe automatically detects the rustypipe-botguard binary if\nit is located in PATH or the current working directory. If your rustypipe-botguard\nbinary is located at a different path, you can specify it with the `.botguard_bin(path)`\noption.\n\n## Authentication\n\nRustyPipe supports authenticating with your YouTube account to access\nage-restricted/private videos and user information. There are 2 supported authentication\nmethods: OAuth and cookies.\n\nTo execute a query with authentication, use the `.authenticated()` query option. This\noption is enabled by default for queries that always require authentication like\nfetching user data. RustyPipe may automatically use authentication in case a video is\nage-restricted or your IP address is banned by YouTube. If you never want to use\nauthentication, set the `.unauthenticated()` query option.\n\n### OAuth\n\nOAuth is the authentication method used by the YouTube TV client. It is more\nuser-friendly than extracting cookies, however it only works with the TV client. This\nmeans that you can only fetch videos and not access any user data.\n\nTo login using OAuth, you first have to get a new device code using the\n`rp.user_auth_get_code()` function. You can then enter the code on\n\u003chttps://google.com/device\u003e and log in with your Google account. After generating the\ncode, you can call the `rp.user_auth_wait_for_login()` function which waits until the\nuser has logged in and stores the authentication token in the cache.\n\n### Cookies\n\nAuthenticating with cookies allows you to use the functionality of the YouTube/YouTube\nMusic Desktop client. You can fetch your subscribed channels, playlists and your music\ncollection. You can also fetch videos using the Desktop client, including private\nvideos, as long as you have access to them.\n\nTo authenticate with cookies you have to log into YouTube in a fresh browser session\n(open Incognito/Private mode). Then extract the cookies from the developer tools or by\nusing browser plugins like \"Get cookies.txt LOCALLY\"\n([Firefox](https://addons.mozilla.org/de/firefox/addon/get-cookies-txt-locally/))\n([Chromium](https://chromewebstore.google.com/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc)).\nClose the browser window after extracting the cookies to prevent YouTube from rotating\nthe cookies.\n\nYou can then add the cookies to your RustyPipe client using the `user_auth_set_cookie`\nor `user_auth_set_cookie_txt` function. The cookies are stored in the cache file. To log\nout, use the function `user_auth_remove_cookie`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteampiped%2Frustypipe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteampiped%2Frustypipe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteampiped%2Frustypipe/lists"}