Phantom downloads 4K+ video and audio. It pushes heavy media work onto your device (browser or phone) instead of a server — so it stays free, ad-free, and unmetered.
Two deployment targets, one codebase:
| Target | What runs where | Repo path |
|---|---|---|
| Web app | Extraction/mux on server (Node), browser mux via mediabunny, server fallback |
web/ |
| Android app | Full pipeline on-device (Expo RN, Hermes, ffmpeg-kit) | mobile/ |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
| Platform | Web | Mobile | Video | Audio | Images | Notes |
|---|---|---|---|---|---|---|
| YouTube | ✅ | ✅ | ✅ | ✅ | ➖ | playlists, shorts, 4K |
| Spotify | ✅ | ✅ | ✅ | ✅ | ➖ | tracks & albums resolve via youtube search |
| SoundCloud | ✅ | ✅ | ➖ | ✅ | ➖ | audio-only service |
| Bilibili | ✅ | ✅ | ✅ | ✅ | ➖ | some videos need a cookie |
| TikTok | ✅ | ✅ | ✅ | ✅ | ✅ | videos + photo carousels |
| ✅ | ✅ | ✅ | ✅ | ✅ | reels, posts, multi-image picker | |
| ✅ | ✅ | ✅ | ✅ | ✅ | public posts only | |
| Threads | ✅ | ✅ | ✅ | ✅ | ✅ | |
| X / Twitter | ✅ | ✅ | ✅ | ✅ | ➖ | videos & gifs only |
| Bluesky | ✅ | ✅ | ✅ | ❌ | ➖ | hls only, no audio |
| Vimeo | ✅ | ✅ | ✅ | ❌ | ➖ | hls only, no audio |
| Dailymotion | ❌ | ✅ | ✅ | ❌ | ➖ | hls only, no audio |
| ❌ | ✅ | ✅ | ✅ | ➖ | ||
| ❌ | ✅ | ✅ | ✅ | ✅ | video pins + photos | |
| Twitch | ❌ | ✅ | ✅ | ❌ | ➖ | clips, hls only |
| Snapchat | ❌ | ✅ | ✅ | ✅ | ➖ | spotlight videos + t.snapchat.com shorts |
# Prerequisites: Node 22+, yt-dlp, ffmpeg, Redis
git clone https://github.com/ejjays/phantom.git
cd phantom
npm install # root tooling (husky, prettier)
npm run install:web # installs frontend, backend, shared
# Create env files (see docs/env-variables.md)
cp web/backend/.env.example web/backend/.env
cp web/frontend/.env.example web/frontend/.env
# Dev (two terminals)
npm run api # backend on :5000
npm run ui # frontend dev serverProduction-style:
npm run build:api
npm run build:ui
cd web/backend && npm startDocker (backend only):
docker build -f web/backend/Dockerfile -t phantom .
docker run -p 8000:8000 --env-file web/backend/.env phantomcd mobile
npm install
npm start # Expo dev client
# or
eas build --profile development # dev client APKPrebuilt APKs: built via EAS on GitHub Actions (build-apk.yml, eas build --local, profiles development/preview/production) and downloadable from the workflow's artifacts. Android only — iOS untested/unsupported.
phantom/
├── web/
│ ├── frontend/ # React 19 + Vite + Tailwind + Styled Components
│ ├── backend/ # Express 5 + yt-dlp + ffmpeg + Redis + Turso
│ └── shared/ # @phantom/shared (Zod schemas)
├── mobile/ # Expo SDK 57, RN 0.86, Hermes, New Arch
│ ├── src/extractors/ # 16 pure-JS platform extractors
│ ├── src/lib/ # download pipeline, social, net, notify
│ └── src/components/ # UI, sheets, backgrounds, webviews
├── packages/
│ ├── extractors/ # @phantom/extractors (shared fb/threads/social)
│ └── web-mux/ # @phantom/web-mux (shared media mux core)
├── scripts/ # termux install, tunnels
└── docs/ # self-host, env, hardening, API, mobile
Key architectural decisions:
- No server for mobile — each phone is its own residential IP + compute. Avoids datacenter bot-blocks and OOM kills on free tiers.
- Client-side muxing is primary —
mediabunny(pure-JS muxer) runs in a Web Worker, streams to OPFS. Server fallback viaffmpeg -c copyonly when client mux fails or browser unsupported. - Googlevideo throttle bypass — backend uses 8 MB ranged chunks, mobile uses 4 MB. Both parallel with per-chunk retry.
| Doc | What it covers |
|---|---|
docs/run-an-instance.md |
Prerequisites, Termux, Docker, tunnels, dev/prod commands |
docs/env-variables.md |
Every env var, defaults, where to get API keys |
docs/protect-an-instance.md |
Hardening a public deployment (API key, URL signing, rate limits, TLS) |
docs/api.md |
Endpoint contracts, request/response shapes, SSE events |
docs/mobile-app.md |
Android app architecture, extractors, download pipeline, EAS build |
docs/phone-worker-setup.md |
Legacy: using a spare phone as yt-dlp/media relay for web backend |
Apache-2.0 for the main apps (web/, mobile/).
MIT for standalone packages in packages/ (@phantom/extractors, @phantom/web-mux) — each carries its own LICENSE.
See LICENSE and packages/*/LICENSE.
Use responsibly. Download only content you have rights to. No piracy.







