| Crates.io | tidlers |
| lib.rs | tidlers |
| version | 0.1.1 |
| created_at | 2026-01-15 16:02:49.900977+00 |
| updated_at | 2026-01-15 16:14:34.150009+00 |
| description | A Rust library for interacting with the TIDAL music streaming API |
| homepage | https://codeberg.org/tomkoid/tidlers |
| repository | https://codeberg.org/tomkoid/tidlers |
| max_upload_size | |
| id | 2045917 |
| size | 180,821 |
A Rust library for interacting with the TIDAL music streaming API.
Tidlers is still very WIP, but here is my project that uses it:
Add this to your Cargo.toml:
[dependencies]
tidlers = "0.1.0"
Or use the git version for the latest features:
[dependencies]
tidlers = { git = "https://codeberg.org/tomkoid/tidlers.git" }
use tidlers::{
TidalClient,
auth::init::TidalAuth,
client::models::playback::AudioQuality,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create client with OAuth authentication
let auth = TidalAuth::with_oauth();
let mut client = TidalClient::new(&auth);
// Get OAuth link for user to authorize
let oauth = client.get_oauth_link().await?;
println!("Visit: https://{}", oauth.verification_uri_complete);
// Wait for authorization
client.wait_for_oauth(
&oauth.device_code,
oauth.expires_in,
oauth.interval,
None,
).await?;
// Get user information
client.refresh_user_info().await?;
println!("Logged in as: {}", client.user_info.unwrap().username);
// Get track information
let track = client.get_track("66035607".to_string()).await?;
println!("Track: {} by {}", track.title, track.artist.name);
// Get playback info for HiRes audio
client.set_audio_quality(AudioQuality::HiRes);
let playback = client.get_track_postpaywall_playback_info("66035607".to_string()).await?;
// Access stream URLs
if let Some(urls) = playback.get_stream_urls() {
println!("Stream URLs: {:?}", urls);
}
Ok(())
}
Tidlers supports all TIDAL audio quality tiers:
HiRes audio uses DASH (Dynamic Adaptive Streaming over HTTP) manifests, which are automatically parsed by the library.
Save and restore sessions to avoid re-authentication:
// Save session
let session_json = client.get_json();
std::fs::write("session.json", session_json)?;
// Load session
let session_data = std::fs::read_to_string("session.json")?;
let mut client = TidalClient::from_serialized(&session_data)?;
// Refresh token if needed
client.refresh_access_token().await?;
let track = client.get_track("track_id".to_string()).await?;
println!("Title: {}", track.title);
println!("Artist: {}", track.artist.name);
println!("Duration: {}s", track.duration);
let album = client.get_album("album_id".to_string()).await?;
// Takes in the album id with optional limit and offset for pagination
let items = client.get_album_items("album_id".to_string(), Some(50), Some(0)).await?;
let playlist = client.get_playlist("playlist_uuid".to_string()).await?;
// Takes in the playlist uuid with optional limit and offset for pagination
let items = client.get_playlist_items("playlist_uuid".to_string(), Some(50), Some(0)).await?;
let mix = client.get_track_mix("track_id".to_string()).await?;
let subscription = client.subscription().await?;
println!("Type: {:?}", subscription.subscription.subscription_type);
For HiRes audio, TIDAL uses DASH streaming. Tidlers parses these manifests automatically:
let playback_info = client.get_track_postpaywall_playback_info(track_id).await?;
match &playback_info.manifest_parsed {
Some(ManifestType::Dash(dash)) => {
println!("Codec: {}", dash.codecs);
println!("Bitrate: {} bps", dash.bitrate.unwrap_or(0));
// Get initialization segment
if let Some(init_url) = dash.get_init_url() {
// Download init segment
}
// Get individual segments
for i in 1..=10 {
if let Some(segment_url) = dash.get_segment_url(i) {
// Download segment i
}
}
}
Some(ManifestType::Json(json)) => {
// Standard JSON manifest for non-HiRes
println!("Direct URL: {}", json.urls[0]);
}
None => {}
}
The repository includes several examples demonstrating different use cases:
Basic example showing authentication, API calls, and data retrieval:
cargo run -p testing-client
This example is also where I test new features during development.
Complete audio streaming example with playback support:
cargo run -p hires-streamer
The library uses the TidalError enum for error handling:
use tidlers::error::TidalError;
match client.get_track(track_id).await {
Ok(track) => println!("Got track: {}", track.title),
Err(TidalError::NotAuthenticated) => println!("Please login first"),
Err(TidalError::Request(e)) => println!("Network error: {}", e),
Err(e) => println!("Other error: {}", e),
}
Core dependencies:
reqwest - HTTP clientserde / serde_json - Serializationtokio - Async runtimebase64 - Base64 encoding/decodingquick-xml - XML parsing for DASH manifeststhiserror - Error handlingBuild the library:
cargo build
Run tests:
cargo test
Run an example:
cargo run -p testing-client
cargo run -p hires-streamer
This project is for educational and personal use. Ensure compliance with TIDAL's Terms of Service.
This is an unofficial library and is not affiliated with or endorsed by TIDAL. Use at your own risk.