tonhowtf/omniget · error
No video URL available
Error message
No video URL available
What it means
For MediaType::Video the library picks the first entry of info.available_qualities as the download source. If that list is empty — the scrape returned video metadata but no playable stream URLs — there is nothing to download and this error is thrown.
Solutions
- Re-fetch a fresh MediaInfo via get_media_info — play URLs expire quickly.
- Check whether the post is actually a video (photo posts have no video qualities).
- Retry with authenticated cookies so TikTok includes playAddr in the response.
- Ensure yt-dlp is installed so fallback quality extraction (yt-dlp-playable format) can populate the list.
Example fix
// before: blind download
let info = tiktok.get_media_info(url).await?;
tiktok.download(&info, &opts).await?;
// after: pre-validate qualities
let info = tiktok.get_media_info(url).await?;
if info.media_type == MediaType::Video && info.available_qualities.is_empty() {
let info = tiktok.get_media_info(url).await?; // re-fetch fresh URLs
anyhow::ensure!(!info.available_qualities.is_empty(), "No video URL available");
}
tiktok.download(&info, &opts).await?; Defensive patterns
Strategy: validation
Validate before calling
let info = tiktok.get_media_info(url).await?;
anyhow::ensure!(
info.media_type != MediaType::Video || !info.available_qualities.is_empty(),
"No video URL available"
); Type guard
fn has_video_url(info: &MediaInfo) -> bool {
info.media_type != MediaType::Video || !info.available_qualities.is_empty()
} Try / catch
match tiktok.download(&info, &opts).await {
Err(e) if e.to_string() == "No video URL available" => {
let fresh = tiktok.get_media_info(url).await?; // re-fetch: URLs may have expired
tiktok.download(&fresh, &opts).await
}
other => other,
} Prevention
- Always download immediately after get_media_info — play URLs expire fast.
- Check media_type: photo/slideshow posts have no video qualities.
- Ensure yt-dlp is installed so fallback quality formats can be extracted.
- Use authenticated cookies so TikTok includes playAddr for logged-out-blocked content.
When it happens
Trigger: download() is called with a MediaInfo whose media_type is Video but available_qualities is empty (quality extraction yielded no tiktok_direct or yt-dlp-playable URLs).
Common situations: TikTok serving the metadata but withholding playAddr for logged-out requests; region-blocked streams filtered out during quality extraction; photo/slideshow posts misdetected as Video; expired play URLs after a stale MediaInfo was cached.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- No video URL available
- Track sem metadata pra resolver no YouTube
- Server returned HTML instead of media — URL may have expired
- No HLS URL available
- No downloadable media found in Threads post
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/0645945ca13b51c0.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/platforms/tiktok.rs:540
opts.concurrent_fragments,
false,
&[],
opts.audio_format.as_deref(),
)
.await;
}
}
let cookies = self.captured_cookies.lock().await.clone();
let mut headers = self.download_headers(&cookies);
crate::core::http_client::inject_ua_header(&mut headers, opts.user_agent.as_deref());
match info.media_type {
MediaType::Video => {
let quality = info
.available_qualities
.first()
.ok_or_else(|| anyhow!("No video URL available"))?;
if quality.format == "tiktok_direct" {
let filename = format!("{}.mp4", sanitize_filename::sanitize(&info.title));
let output = opts.output_dir.join(&filename);
let result = direct_downloader::download_direct_with_headers(
&self.client,
&quality.url,
&output,
progress.clone(),
Some(headers),
Some(&opts.cancel_token),
)
.await;
match result {
Ok(bytes) => {
return Ok(DownloadResult {View on GitHub (pinned to 8600b91f42)