⬇️ Download Latest APK | 📜 Release Notes | 📋 Changelog
An Android application for downloading videos and media from the web with a built-in browser, multi-threaded download engine, and private vault.
- In-App Browser — Full WebView with incognito mode, HTTPS-only toggle, tracker blocking, bookmarking, and media detection via JavaScript bridge
- Multi-Threaded Download Engine — Segmented (chunked) downloads with pause/resume, real-time speed tracking, and adaptive threading
- Analyze-First UX — Paste any link on the dashboard, tap Analyze, see platform info + quality options, then download
- Multi-Platform Video Downloader — Supports TikTok, Instagram, Facebook, Twitter/X, Reddit, Pinterest, SoundCloud, Vimeo, Twitch, Dailymotion, Tumblr, Steam, and ANY website via generic fallback extraction
- TikTok Downloader — TikWM API + 9 fallback strategies for HD no-watermark, watermarked, and audio-only downloads
- Instagram Downloader — 3-strategy chain: GraphQL POST API (doc_id + X-IG-App-ID, primary), page HTML with Firefox desktop headers (og:video fallback), JSON-LD VideoObject (tertiary); cookie-authenticated session via InstagramLoginActivity WebView
- Facebook Downloader — 3-strategy custom extraction (m.facebook.com → www → mbasic), no yt-dlp dependency, User-Agent: facebookexternalhit/1.1 for CDN, cookie injection, share URL resolution
- Pinterest Downloader — 5-strategy extraction: og:video, JSON-LD VideoObject, relay script data with brace-counting JSON parser, contentUrl regex, pinimg CDN URL; pin.it short URL resolution; browser headers for server-side rendering
- Twitter/X Downloader — og:video, twitter:player:stream, and CDN URL extraction
- Steam Downloader — Embedded Steam video page extraction via video URL patterns
- Generic Fallback — 10 extraction strategies for ANY website (og:video, JSON-LD, video tags, CDN patterns, etc.)
- Social Media Authentication — WebView-based Instagram and Facebook login for cookie-captured extraction
- Media Detection — Automatically detects
<video>and downloadable media links on web pages - Download Queue — Active downloads section with progress bars, speed indicators, estimated remaining time, and health badges
- Private Vault — PIN-protected secure storage for sensitive downloads; files hidden from device gallery
- File Library — Completed downloads browser with category filtering (Video/Audio/Images/Other), video playback, file sharing, and move-to-vault
- Download Health Monitoring — Background WorkManager worker that periodically verifies file integrity and connection health
- Customizable Theme — Light, Dark, System, and AMOLED Black modes with 13 accent colors
- Storage Management — Visual storage overview with video/audio size breakdown and one-tap cache optimization
| Layer | Technology |
|---|---|
| Language | Kotlin |
| UI | Jetpack Compose + Material 3 |
| Architecture | MVVM with Repository Pattern |
| Database | Room (SQLite) via Kotlin Coroutines Flow |
| Networking | OkHttp 4.x, Moshi |
| Browser Engine | Android WebView with JavaScript Interface |
| Background Work | WorkManager 2.9.x |
| Image Loading | Coil |
| Security | Encrypted SharedPreferences, FileProvider |
| Min SDK | 24 (Android 7.0) |
| Target SDK | 36 (Android 16) |
| File | Size | SHA-256 |
|---|---|---|
| app-release.apk | TBD | TBD (CI in progress) |
| app-release.aab | TBD | TBD (CI in progress) |
- Android 7.0 (API 24) or higher
- ARM64 / ARM / x86_64
- Open the project in Android Studio.
- Sync Gradle and build the
appmodule.
Release builds require the following environment variables:
KEYSTORE_PATHKEYSTORE_PASSWORDKEY_ALIASKEY_PASSWORD
Debug builds use a local debug.keystore with default credentials.
app/src/main/java/com/example/
├── MainActivity.kt # Entry point with bottom navigation
├── ui/
│ ├── viewmodel/MainViewModel.kt # Central ViewModel (StateFlow + Room)
│ ├── screens/
│ │ ├── DashboardTab.kt # Home dashboard with analyze-first link input
│ │ ├── BrowserTab.kt # WebView browser with media detection
│ │ ├── DownloadsTab.kt # Download queue (active + completed)
│ │ ├── FilesTab.kt # File library with categories
│ │ ├── VaultTab.kt # PIN-protected private vault
│ │ ├── SettingsTab.kt # Preferences, theme, social media login, about
│ │ ├── InstagramLoginActivity.kt # WebView-based Instagram login for cookie capture
│ │ ├── FacebookLoginActivity.kt # WebView-based Facebook login for cookie capture
│ │ ├── stream/
│ │ │ └── StreamDownloadCard.kt # Stream download quality/card UI
│ │ └── browser/
│ │ └── BrowserMediaSheet.kt # Browser media detection bottom sheet
│ ├── components/ # Reusable composables
│ │ ├── TabHeader.kt # Section header with category + title
│ │ ├── DownloadHealthIndicators.kt # Integrity & connection health badges
│ │ ├── DownloadDialog.kt # Quality selection, thread count, privacy toggle
│ │ ├── VideoPlayerDialog.kt # Full-screen video player
│ │ └── PatternLockView.kt # Canvas-based PIN pattern lock for vault
│ └── theme/ # Colors, typography, theme system
├── data/
│ ├── database/ # Room entities, DAOs, database
│ │ ├── Entities.kt # DownloadEntity, BookmarkEntity, HistoryEntity
│ │ ├── DAOs.kt # DownloadDao, queries
│ │ └── AppDatabase.kt # Room database singleton
│ └── download/ # Download engine + extractors
│ ├── BaseExtractor.kt # Shared data types, cookie stores, utilities
│ ├── DownloadEngine.kt # Multi/single-thread download manager
│ ├── MediaUtils.kt # Formatting, filename parsing
│ ├── DownloadIntegrityWorker.kt # Periodic health checks via WorkManager
│ ├── VideoExtractor.kt # Multi-platform extraction router (20+ platforms)
│ └── stream/ # Platform-specific stream extractors
│ ├── TikTokExtractor.kt # TikWM API + 9 fallback strategies
│ ├── TikTokCookieStore.kt # Shared CookieJar for TikTok requests
│ ├── InstagramExtractor.kt # GraphQL POST → page HTML → JSON-LD
│ ├── FacebookExtractor.kt # m.facebook → www → mbasic extraction
│ ├── TwitterExtractor.kt # og:video + player:stream + CDN
│ ├── RedditExtractor.kt # JSON API extraction
│ ├── PinterestExtractor.kt # 5-strategy extraction
│ ├── SoundCloudExtractor.kt # oEmbed + og:audio
│ ├── VimeoExtractor.kt # oEmbed extraction
│ ├── TwitchExtractor.kt # og:video + CDN
│ ├── DailymotionExtractor.kt# oEmbed extraction
│ ├── TumblrExtractor.kt # og:video + CDN
│ ├── YtDlpExtractor.kt # yt-dlp wrapper (youtubedl-android)
│ └── GenericExtractor.kt # 10-strategy fallback for any website
Instagram video extraction uses a 3-strategy pipeline in InstagramExtractor.kt:
POST https://www.instagram.com/graphql/query
Content-Type: application/x-www-form-urlencoded
X-IG-App-ID: 1217981644879628
X-CSRFToken: <from cookie>
X-FB-LSD: AVqbxe3J_YA- Sends
doc_id=10015901848480474+variables(shortcode JSON) in form body - Response contains
data.xdt_shortcode_media.video_url— the direct CDN video URL - This is the SAME approach used by working open-source repos (Okramjimmy/Instagram-reels-downloader)
- Fetches page HTML with Firefox desktop User-Agent + Instagram-specific Sec-Fetch headers
- Instagram returns server-rendered HTML with
<meta property="og:video">containing the direct CDN URL - Without these specific headers, Instagram returns empty JS-rendered shell
- Parses
<script type="application/ld+json">for VideoObject withcontentUrl
- Old GraphQL: Used GET with
query_hash=4777bf1659f3c198a0be3bb630125cce— Instagram deprecated this - __additionalData / __shareConfig: These JavaScript variables no longer exist in Instagram's HTML
- Generic headers: Returned empty HTML without video data
- Users can log in via WebView (
InstagramLoginActivity) to capture session cookies - Cookies are stored in
InstagramCookieStore(SharedPreferences) - GraphQL requests extract
X-CSRFTokenfrom cookies automatically - Without cookies, public reels/posts still work — login improves reliability
Facebook video extraction uses a 4-strategy pipeline in FacebookExtractor.kt:
- Rewrites URL to
m.facebook.com— mobile page has simplest HTML - Parses
<video>tags withhd_src/sd_srcattributes for direct CDN URLs - Also extracts from script data containing
playable_urlpatterns - Most reliable — avoids Facebook's aggressive rate-limiting on desktop pages
- Desktop page HTML with JSON-LD VideoObject extraction
- Script data patterns for
hd_src/sd_srcin embedded JSON - DASH manifest
BaseURLextraction for modern Facebook video pages
- Oldest/simplest HTML format with direct
<video>tagsrcattributes - Used when both mobile and desktop pages fail
- Facebook's oEmbed endpoint (
https://www.facebook.com/plugins/video/oembed.json) - Returns thumbnail URL and occasionally a direct video URL
- Used as final fallback before giving up
- Facebook share URLs (
/share/r/xxx) are resolved to actual video page URLs via HEAD/GET request with Android Chrome User-Agent
- yt-dlp (youtubedl-android) hangs indefinitely on Facebook URLs
- When it does return, it frequently returns HTTP 403 Forbidden on CDN URLs
- Custom extraction is faster and more reliable
- User-Agent: Uses
facebookexternalhit/1.1inBaseExtractor.fetchPageHtml()for Facebook CDN — this is required to avoid 403 onfbcdn.netURLs - Cookie Injection: Facebook login cookies can be captured via WebView (
FacebookLoginActivity) for access to private/restricted videos - DASH vs MP4: Modern Facebook serves separate audio+video DASH streams — the CDN URL may be a manifest, not a direct MP4
- Token Expiry: CDN tokens (
oh=,oe=,_nc_sid=) expire in ~30-60 minutes — download immediately after extraction
TikTok video extraction uses a 10-strategy pipeline in TikTokExtractor.kt:
POST https://www.tikwm.com/api/
Content-Type: application/x-www-form-urlencoded- Sends
url=<tiktok-url>&hd=1as form body - TikWM returns processed video data with direct CDN URLs
- Falls back to GET
https://www.tikwm.com/api/?url=<encoded-url>&hd=1if POST fails - Returns HD no-watermark video, watermarked video, and audio-only options
- Alternative third-party API (ssstik.io) for direct video extraction
- Used when TikWM API is unreachable or rate-limited
- Extracts video
itemIdfrom the URL (or HTML) - Sends request to TikTok's internal mobile API endpoint
- Returns JSON with video URLs, author info, and metadata
When API strategies fail, the page HTML is fetched and parsed with 6 methods:
- Universal Data — Parses
<script id="__UNIVERSAL_DATA_FOR_VIEW_INITIAL_DATA__"> - Init Props — Parses
<script id="__INITIAL_PROPS_INITIAL_STATE__"> - Sigi Data — Parses
<script id="SIGI_STATE">(client-side state) - CDN URL Pattern — Regex search for direct TikTok CDN URLs in any script
- Meta Tags —
og:video,og:video:secure_url,twitter:player:stream - JSON-LD VideoObject —
<script type="application/ld+json">parsing - Video Tags — Any
<video>tagsrcattributes in the page
- TikTok's oEmbed endpoint:
https://www.tiktok.com/oembed?url=<itemId> - Returns metadata and thumbnail URL
Pinterest video extraction uses a 5-strategy pipeline in PinterestExtractor.kt:
- Checks
<meta property="og:video">for direct video URL - Rare in modern Pinterest (2025+) but checked first for simplicity
- Parses
<script type="application/ld+json">for VideoObject withcontentUrl - Most reliable strategy — Pinterest includes this on video pins
- Content URL format:
https://v1.pinimg.com/videos/.../720p.mp4
- Parses
__PWS_RELAY_REGISTER_COMPLETED_REQUEST__scripts - Uses brace-counting JSON parser (
extractBalancedJson()) — tracks{depth and string escaping to extract the complete nested JSON object - Old regex
[\s\S]*?\}broke on deeply nested JSON (stopped at first}) - Video data located at:
storyPinData.pages[].blocks[].videoDataV2videoList720P.v720P.url— MP4 (preferred)videoListMobile.vHLSV3MOBILE.url— m3u8 (fallback)
- Direct regex:
"contentUrl"\s*:\s*"(https:\\/\\/v1\.pinimg\.com[^"]+\.mp4)" - Bypasses JSON parser when JSON-LD has duplicate keys that cause parse failures
- Searches entire HTML for any
v1.pinimg.comURL ending in.mp4 - Pinterest CDN has no authentication issues — always accessible
pin.itshort URLs (e.g.,https://pin.it/2ima6B8Wm) are resolved to fullhttps://www.pinterest.com/pin/{id}/URLs via redirect following
- Missing relay data: Without browser
Sec-Fetch-*andSec-Ch-Uaheaders, Pinterest returns empty JavaScript shell — no relay scripts - Broken regex:
[\s\S]*?\}is non-greedy and stops at first}, yielding partial JSON that fails to parse — fixed with brace-counting - Unresolved short URLs:
resolveRedirect()only handled TikTok short URLs — addedisShortPinterestcheck
| Platform | Extraction Method |
|---|---|
| TikTok | TikWM API + 9 fallback strategies |
| GraphQL POST (doc_id + X-IG-App-ID) → page og:video → JSON-LD VideoObject | |
| m.facebook.com (primary) → www → mbasic, facebookexternalhit/1.1 UA, cookie injection | |
| Twitter/X | og:video + twitter:player:stream + CDN |
| JSON API extraction | |
| og:video + JSON-LD + relay data (brace-counting) + contentUrl regex + CDN URL | |
| SoundCloud | oEmbed + og:audio |
| Vimeo | oEmbed extraction |
| Twitch | og:video + CDN |
| Dailymotion | oEmbed extraction |
| Tumblr | og:video + CDN |
| Steam | Embedded Steam video page extraction |
| Any Website | 10-strategy generic fallback |
- GitHub: github.com/abir2afridi
- Portfolio: abir2afridi.vercel.app
- Computer Science · Independent University of Bangladesh
- Contributing Guidelines — How to contribute, code style, PR process
- Code of Conduct — Community standards and enforcement
- Security Policy — Reporting vulnerabilities
- Support — Where to get help
- Issue Templates — Bug reports, feature requests, and more
- Pull Request Template — PR submission guidelines
MIT License — feel free to use, modify, and distribute.
