tonhowtf/omniget · error · anyhow::Error

No media found in embed

Error message

No media found in embed

What it means

Raised by `extract_media_from_embed` when the fetched embed HTML yields no `video_url` and no `display_url` — i.e. the parsed embed data contains no image or video the extractor recognizes. Like its GraphQL sibling (1111), it is the 'no downloadable media' sentinel for the embed path.

Solutions

  1. Open the embed URL manually (https://www.instagram.com/p/<id>/embed/) to check whether media actually renders
  2. Use `fallback_ytdlp` (yt-dlp) which tracks Instagram markup upstream and is more resilient to markup changes
  3. Update the embed selectors/field names in `extract_media_from_embed` to the current Instagram markup
  4. Retry with browser-like headers (`instagram_headers`) or a residential IP if the wall/limit page is the cause

Example fix

// before
let media = self.extract_media_from_embed(&html)?;
// after
match self.extract_media_from_embed(&html) {
    Ok(m) => Ok(m),
    Err(e) => {
        tracing::warn!("embed media missing: {e:#}; delegating to yt-dlp");
        self.fallback_ytdlp(url, &post_id).await
    }
}
Defensive patterns

Strategy: fallback

Validate before calling

fn embed_has_media(data: &serde_json::Value) -> bool {
    data.get("video_url").map_or(false, |v| v.is_string())
        || data.get("display_url").map_or(false, |v| v.is_string())
}

Type guard

fn has_media_url(v: &serde_json::Value) -> bool {
    v.get("video_url").and_then(|x| x.as_str()).is_some()
        || v.get("display_url").and_then(|x| x.as_str()).is_some()
}

Try / catch

match extract_media_from_embed(&html) {
    Ok(m) => m,
    Err(e) if e.to_string().contains("No media found in embed") => {
        downloader.fallback_ytdlp(url, &post_id).await?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `extract_media_from_embed` on embed-page data where neither a video URL nor a display image URL was found: removed/private posts, new Instagram embed markup, or embed pages served as a login/consent wall.

Common situations: Instagram renames `display_url`/`video_url` in embed output; the embed endpoint returns an error page instead of media; the post is a story or unsupported type embedded in the page; rate limiting returns a stub page.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/120956f68e138dd8. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/src/platforms/instagram/mod.rs:638

            return Ok(InstagramMedia::Single {
                url: video_url.to_string(),
                is_video: true,
            });
        }

        if let Some(display_url) = data
            .get("media")
            .and_then(|m| m.get("display_url"))
            .or_else(|| data.get("display_url"))
            .and_then(|v| v.as_str())
        {
            return Ok(InstagramMedia::Single {
                url: display_url.to_string(),
                is_video: false,
            });
        }

        Err(anyhow!("No media found in embed"))
    }
}

fn base64_url_encode(bytes: &[u8]) -> String {
    use base64::Engine;
    base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(bytes)
}

#[async_trait]
impl PlatformDownloader for InstagramDownloader {
    fn name(&self) -> &str {
        "instagram"
    }

    fn can_handle(&self, url: &str) -> bool {
        if let Ok(parsed) = url::Url::parse(url) {
            if let Some(host) = parsed.host_str() {
                let host = host.to_lowercase();

View on GitHub (pinned to 8600b91f42)