JavaTube is a YouTube video download library based on pytube library.
JavaTube is a library written in java and aims to be highly reliable.
- Support for downloading the full playlist
- Support for progressive and adaptive streams
- Interaction with channels (Videos, YouTube Shorts, lives and Playlists)
- onProgress callback register
- Keyword search support
- Ability to get video details (Title, Description, Publish Date, Length, Thumbnail Url, Views, Author and Keywords)
- Subtitle generator for .srt format
- Support downloading yt_otf streams
- Possibility to choose the client (WEB, ANDROID, IOS)
- Native js interpreter
- PoToken support
Currently this project is maintained by only one person. Feel free to create issues with questions, bug reports or improvement ideas.
This code is for educational purposes and must not be used in any way for commercial purposes.
Downloading videos from YouTube without proper authorization may violate the terms of the platform.
Downloading copyrighted videos may infringe on the creators' intellectual property.
I reaffirm not to use this software to violate any laws.
To download YouTube videos you need to import the YouTube class and pass a YouTube video url to access the streams.
The streams() method returns a StreamQuery object that lists the properly handled streams.
You must only get one stream to be able to download it. You can use the methods:
getHighestResolution()
getLowestResolution()
getOnlyAudio()
You can also manually select the stream using .get("index")
.
The download() method must receive the path that the stream will be downloaded.
public static void main(String[] args) throws Exception {
Youtube yt = new Youtube("https://www.youtube.com/watch?v=2lAe1cqCOXo");
yt.streams().getHighestResolution().download("./");
}
or
public static void main(String[] args) throws Exception {
new Youtube("https://www.youtube.com/watch?v=2lAe1cqCOXo").streams().get(1).download("./");
}
}
Videos with multiple progressive audio tracks come with the original audio, which is why we must choose the adaptive types.
Because the dubbed audio tracks have the same tag, we have to filter by name.
This will only list tracks dubbed in the chosen language:
public static void main(String[] args) throws Exception {
for(Stream s : new Youtube("https://www.youtube.com/watch?v=g_VxOIlg7q8").streams().getExtraAudioTracksByName("English").getAll()){
System.out.println(s.getItag() + " " + s.getAudioTrackName() + " " + s.getAbr() + " " + s.getUrl());
}
}
You can check the dubbed tracks using:
public static void main(String[] args) throws Exception {
for(Stream s : new Youtube("https://www.youtube.com/watch?v=g_VxOIlg7q8").streams().getExtraAudioTracks().getAll()){
System.out.println(s.getItag() + " " + s.getAudioTrackName() + " " + s.getAbr() + " " + s.getUrl());
}
}
You must pass a HashMap String with the filter you want to use and its respective value
public static void main(String[] args) throws Exception {
Youtube yt = new Youtube("https://www.youtube.com/watch?v=2lAe1cqCOXo");
HashMap<String, String> filters = new HashMap<>();
filters.put("progressive", "true");
filters.put("subType", "mp4");
yt.streams().filter(filters).getFirst().download("./");
}
If no parameter is passed, a download percentage string will be printed to the terminal
public static void progress(Long value){
System.out.println(value);
}
public static void main(String[] args) throws Exception {
Youtube yt = new Youtube("https://www.youtube.com/watch?v=2lAe1cqCOXo");
yt.streams().getHighestResolution().download("./", Download::progress);
}
The getVideos()
method will return an ArrayList with the links extracted from the playlist url (YouTube mix not supported)
public static void main(String[] args) throws Exception {
for(String pl : new Playlist("https://www.youtube.com/playlist?list=PLS1QulWo1RIbfTjQvTdj8Y6yyq4R7g-Al").getVideos()){
new Youtube(pl).streams().getHighestResolution().download("./");
}
}
-
getResults()
: method will return an ArrayList with links to videos, shorts, playlists and channels. -
getVideoResults()
: method returns an ArrayList of Youtube objects, containing videos. -
getShortsResults()
: method returns an ArrayList of Youtube objects, containing YouTube Shorts. -
getChannelsResults()
: method returns an ArrayList of Channel objects, containing the channels. -
getPlaylistsResults()
: method returns an ArrayList of Playlist objects, containing the playlists. -
getCompletionSuggestions()
: method returns a list containing search suggestions. -
generateContinuation()
: method will not return anything, just add the continuation of the items to their respective lists.
If no match was found the method will return empty, other than getCompletionSuggestions()
which returns null.
public static void main(String[] args) throws Exception {
for(String yt : new Search("Java").getResults()){
System.out.println(yt);
}
}
-
getVideos()
: method returns an ArrayList containing the channel's videos. -
getShorts()
: method returns an ArrayList containing the channel's YouTube Shorts. -
getLives()
: method returns an ArrayList containing the channel's lives. -
getPlaylists()
: method returns an ArrayList containing the channel's playlists.
public static void main(String[] args) throws Exception {
for(String c : new Channel("https://www.youtube.com/channel/UCmRtPmgnQ04CMUpSUqPfhxQ").getVideos()){
System.out.println(new Youtube(c).getTitle());
}
}
See available languages.
public static void main(String[] args) throws Exception {
for(Captions caption: new Youtube("https://www.youtube.com/watch?v=2lAe1cqCOXo&t=1s").getCaptionTracks()){
System.out.println(caption.getCode());
}
}
Write to console in .srt format.
public static void main(String[] args) throws Exception {
System.out.println(new Youtube("https://www.youtube.com/watch?v=2lAe1cqCOXo&t=1s").getCaptions().getByCode("en").xmlCaptionToSrt());
}
Download it in .srt format (if the .srt format is not informed, the xml will be downloaded).
public static void main(String[] args) throws Exception {
new Youtube("https://www.youtube.com/watch?v=2lAe1cqCOXo&t=1s").getCaptions().getByCode("en").download("caption.srt", "./")
}
The proof of origin (PO) token is a parameter that YouTube requires to be sent with video playback requests from some clients. Without it, format URL requests from affected customers may return HTTP error 403, error with bot detection, or result in your account or IP address being blocked.
This token is generated by BotGuard (Web) / DroidGuard (Android) to attest the requests are coming from a genuine client.
This process involves manually obtaining a PO token generated from YouTube in a web browser and then manually passing it to JavaTube via the usePoToken=True argument. Steps:
-
Open a browser and go to any video on YouTube Music or YouTube Embedded (e.g. https://www.youtube.com/embed/2lAe1cqCOXo). Make sure you are not logged in to any account!
-
Open the developer console (F12), then go to the "Network" tab and filter by v1/player
-
Click the video to play and a player request will appear in the network tab
-
In the request payload JSON, find the PO Token at serviceIntegrityDimensions.poToken and save that value
-
In the request payload JSON, find the visitorData at context.client.visitorData and save that value
-
In your code, pass the parameter usePoToken=True, to send the visitorData and PoToken:
public static void main(String[] args) throws Exception {
Youtube yt = new Youtube("https://www.youtube.com/watch?v=2lAe1cqCOXo", true);
yt.streams().getHighestResolution().download("./");
}
The terminal will ask you to insert the tokens.
If you want to save the token in cache, just add one more argument true
, this will create a cache/tokens.json file where the visitorData and poToken will be stored.
-
"res"
The video resolution (e.g.: "360p", "720p") -
"fps"
The frames per second (e.g.: "24fps", "60fps") -
"mineType"
Two-part identifier for file formats and format contents composed of a “type”, a “subtype” (e.g.: "video/mp4", "audio/mp4") -
"type"
Type part of the mineType (e.g.: audio, video) -
"subType"
Sub-type part of the mineType (e.g.: mp4, webm) -
"abr"
Average bitrate (e.g.: "128kbps", "192kbps") -
"videoCodec"
Video compression format -
"audioCodec"
Audio compression format -
"onlyAudio"
Excludes streams with video tracks (e.g.: "true" or "false") -
"onlyVideo"
Excludes streams with audio tracks (e.g.: "true" or "false") -
"progressive"
Excludes adaptive streams (one file contains both audio and video tracks) (e.g.: "true" or "false") -
"adaptive"
Excludes progressive streams (audio and video are on separate tracks) (e.g.: "true" or "false")