https://github.com/ibrahimjspy/insta-like-player
Turn your liked Instagram, TikTok & Facebook videos into a private, searchable, self-hosted video library — official exports + yt-dlp, no scraping.
https://github.com/ibrahimjspy/insta-like-player
data-hoarding facebook instagram media-server nextjs personal-archive postgresql prisma reels self-hosted self-hosting tiktok typescript video-library yt-dlp
Last synced: 25 days ago
JSON representation
Turn your liked Instagram, TikTok & Facebook videos into a private, searchable, self-hosted video library — official exports + yt-dlp, no scraping.
- Host: GitHub
- URL: https://github.com/ibrahimjspy/insta-like-player
- Owner: ibrahimjspy
- License: mit
- Created: 2026-05-31T16:14:55.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-06-08T13:49:54.000Z (about 1 month ago)
- Last Synced: 2026-06-08T15:29:10.097Z (about 1 month ago)
- Topics: data-hoarding, facebook, instagram, media-server, nextjs, personal-archive, postgresql, prisma, reels, self-hosted, self-hosting, tiktok, typescript, video-library, yt-dlp
- Language: TypeScript
- Size: 5.69 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# Like Player
**Turn your liked videos into a private, searchable, TikTok-style library.**
Import likes from Instagram, TikTok, and Facebook using each platform's official
data export. Download the media locally with `yt-dlp`. Browse everything in a
fast web app — vertical feed, full-text search, favorites, and custom collections.
Not affiliated with Meta, ByteDance, or any social platform. Use only with **your
own** exported data.
[](LICENSE)
[](https://github.com/ibrahimjspy/insta-like-player/actions/workflows/ci.yml)
[](package.json)
[](https://nextjs.org)

For you feed — vertical, snap-scrolling, ranked by your watch behavior
---
## Screenshots
Search — caption, creator, or hashtag, filtered by platform

Admin dashboard — library stats, per-platform import, and live sync

Collections — curate subsets without touching the original platforms

---
## Contents
[Why this exists](#why-this-exists) ·
[How it works](#how-it-works) ·
[Features](#features) ·
[Supported platforms](#supported-platforms) ·
[Quick start](#quick-start) ·
[Configuration](#configuration) ·
[FAQ](#faq) ·
[Roadmap](#roadmap) ·
[Self-hosting](#self-hosting) ·
[Legal & privacy](#legal--privacy)
---
## Why this exists
Social platforms bury your likes in export ZIPs and expired CDN links. Like Player
gives you:
- **One library** for Instagram Reels, TikTok videos, and Facebook saved/reacted videos
- **Local files** — no streaming from expired URLs; seekable playback from disk
- **A real feed** — Recent, Oldest, or a **For you** ranker that learns from watch time
- **Search** — caption, creator, hashtag, and platform filters
- **Collections & favorites** — curate subsets without touching the original platforms
- **Self-hosted** — single-user, runs on your machine; optional Tailscale access from your phone
No scraping. No login automation. Discovery comes from official exports; downloads
use `yt-dlp` with optional session cookies you provide.
### Why not just keep the export?
| Instead of… | …you get with Like Player |
|-------------|---------------------------|
| A `liked_posts.json` you'll never open again | A scrollable, watchable feed of the actual videos |
| Saves & bookmarks that vanish when posts are deleted | Local copies that survive takedowns and expired CDN links |
| A folder of `yt-dlp` files named by ID | Captions, creators, hashtags, search, and collections |
| Re-finding things at the algorithm's whim | A **For you** feed ranked by *your* watch behavior |
---
## How it works
```
Platform export (JSON) ──► ingest ──► PostgreSQL ◄── sync (yt-dlp) ──► data/media
│
▼
Next.js web app
Reader (/) · Admin (/admin)
```
| Step | What happens |
|------|----------------|
| **Import** | Parse `liked_posts.json`, `user_data_tiktok.json`, or Facebook `posts_and_comments.json` / saved collections into the DB |
| **Sync** | Download video + thumbnail + metadata for each pending item |
| **Browse** | Stream from `/api/media/...` with HTTP range support (scrubbing works) |
---
## Features
### Reader (`/`)
- Infinite vertical feed with tap-to-pause chrome
- Sort: **Recent** · **Oldest** · **For you** (personalized from watch behavior)
- Auto-scroll and video-only modes while paused
- Search by text, creator, or platform
- Favorites and user-defined collections
### Admin (`/admin`)
- Upload exports per platform
- Run and monitor background sync
- Inspect reel status (pending, downloaded, failed, unavailable)
### For you feed
Not random — ranks reels from engagement signals (watch time, loops, deep watches
vs quick skips, creator/hashtag/collection affinity). Tune weights in
`src/lib/feed/config.ts`. Design doc: [docs/FEED_RECOMMENDATIONS.md](docs/FEED_RECOMMENDATIONS.md).
---
## Supported platforms
| Platform | Export file | CLI flag |
|----------|-------------|----------|
| Instagram | `liked_posts.json` (Likes, JSON, all time) | `--platform instagram` (default) |
| TikTok | `user_data_tiktok.json` (include **Likes**) | `--platform tiktok` |
| Facebook | `likes_and_reactions/posts_and_comments.json`, saved collections, or `your_saved_items.json` | `--platform facebook` |
Each platform uses the same pipeline; media is stored as
`_.mp4` (Instagram keeps bare shortcodes for backward compatibility).
---
## Quick start
**Prerequisites:** Node.js 20+, Docker (for Postgres), [`yt-dlp`](https://github.com/yt-dlp/yt-dlp)
```bash
git clone https://github.com/ibrahimjspy/insta-like-player.git
cd insta-like-player
npm install
cp .env.example .env # edit DATABASE_URL if port 5432 is taken
npm run db:up && npm run db:push
npm run dev # http://localhost:3000
```
### Import your likes
**Admin UI:** open `/admin` → pick platform → upload JSON → Sync.
**CLI:**
```bash
# Instagram (default)
npm run ingest -- path/to/liked_posts.json
# TikTok
npm run ingest -- --platform tiktok path/to/user_data_tiktok.json
# Facebook
npm run ingest -- --platform facebook path/to/posts_and_comments.json
npm run sync # download pending media
npm run sync -- --limit 50 # batch of 50
npm run sync -- --retry # include previously failed reels
```
### Cookies (the key to reliable downloads)
Discovery (the list of your likes) comes from the export and needs no login. But
the **download** step does: platforms gate reel/video media behind a session, so
`yt-dlp` needs your browser cookies to fetch it. Without cookies most downloads
fail or get rate-limited fast — this is the single most important setup step.
**1. Export a `cookies.txt` (Netscape format).** While logged into the platform in
your browser, use a cookie-export extension such as
**"Get cookies.txt LOCALLY"** (open source, runs locally). Export **as
`cookies.txt` (Netscape format, _not_ JSON)** while the platform's site is open.
A valid file starts with `# Netscape HTTP Cookie File` and, for Instagram,
contains `sessionid`, `ds_user_id`, and `csrftoken`.
**2. Save it and point `.env` at it** (per platform you'll download from):
```bash
YTDLP_COOKIES_INSTAGRAM="./data/cookies-instagram.txt"
YTDLP_COOKIES_TIKTOK="./data/cookies-tiktok.txt"
YTDLP_COOKIES_FACEBOOK="./data/cookies-facebook.txt"
```
**3. Verify it works** before a big sync:
```bash
yt-dlp --cookies data/cookies-instagram.txt -o "data/_test.%(ext)s" \
"https://www.instagram.com/reel/SHORTCODE/" # any reel you can view
# success = an .mp4 appears, then: rm data/_test.*
```
> **`cookies.txt` is a live session credential — treat it like a password.** It's
> gitignored (everything under `data/` is). Never commit or share it. Logging out
> or changing your password invalidates it. To minimize account risk, you can use
> a throwaway/secondary session and keep `SYNC_RATE_LIMIT_MS` polite (≥ 4000).
TikTok also often needs browser impersonation (a `curl_cffi`-enabled yt-dlp
build) — see the commented setup in `.env.example`.
---
## Configuration
All settings flow through `.env` → `src/lib/config.ts`:
| Variable | Default | Description |
|----------|---------|-------------|
| `DATABASE_URL` | local Docker Postgres | PostgreSQL connection string |
| `MEDIA_DIR` | `./data/media` | Downloaded videos and thumbnails |
| `FEED_PAGE_SIZE` | `10` | Reels per infinite-scroll page |
| `YTDLP_PATH` | `yt-dlp` | Path to yt-dlp binary |
| `YTDLP_COOKIES_*` | _(unset)_ | Per-platform Netscape cookies |
| `YTDLP_IMPERSONATE_TIKTOK` | `chrome` | TLS fingerprint for TikTok 403s |
| `SYNC_RATE_LIMIT_MS` | `4000` | Delay between sequential downloads |
| `SYNC_MAX_RETRIES` | `3` | Retries before marking FAILED |
| `SYNC_REELS_ONLY` | `true` | Skip non-video likes (e.g. Instagram `/p/` photos) |
---
## Scripts
| Command | Description |
|---------|-------------|
| `npm run dev` | Development server |
| `npm run build` | Production build + typecheck |
| `npm test` | Vitest unit tests |
| `npm run lint` | ESLint |
| `npm run ingest` | Import a platform export |
| `npm run sync` | Download pending reels |
| `npm run db:up` / `db:down` | Start/stop Postgres container |
| `npm run db:push` | Apply Prisma schema |
| `npm run serve` | Production server on port 7319 |
---
## Project structure
```
prisma/schema.prisma Reels, creators, hashtags, collections, engagement
src/lib/platforms/ Instagram, TikTok, Facebook export parsers
src/lib/feed/ For you scoring, taste classification, SQL ranker
src/lib/queries.ts Feed, search, collections, favorites
src/app/(reader)/ Feed, search, collections, favorites
src/app/admin/ Import, sync, reel management
src/app/api/media/ Local media streaming with range requests
docs/ FEED_RECOMMENDATIONS.md, DEPLOYMENT.md
```
---
## Self-hosting
Run as an always-on personal server and reach it from your phone over
[Tailscale](https://tailscale.com) — no cloud, no public exposure. See
**[docs/DEPLOYMENT.md](docs/DEPLOYMENT.md)**.
```bash
npm run build
bash scripts/install-service.sh # macOS launchd agent on port 7319
tailscale serve --bg 7319 # private HTTPS on your tailnet
```
---
## Testing
```bash
npm test # full suite
npm test -- src/lib/feed # after feed algorithm changes
```
Tests cover export parsers (all three platforms), feed pagination and scoring,
search filters, media path safety, and yt-dlp helpers. Prisma is mocked — no DB
required.
---
## Tech stack
Next.js 16 (App Router) · TypeScript · Tailwind CSS v4 · PostgreSQL · Prisma 7 ·
`yt-dlp` · Docker Compose · Vitest
---
## FAQ
**Will my account get banned?**
Downloads are read-only and rate-limited — sequential, one at a time, with
`SYNC_RATE_LIMIT_MS` ≥ 4000 by default. The app never likes, follows, comments,
or posts. As with any `yt-dlp` use there's mild risk on a main account; go slow,
or use a throwaway session for the cookies.
**Is this legal?**
You only process **your own** exported data and download content you already
liked. The app doesn't bypass access controls or scrape. Automated downloading
may still conflict with a platform's Terms of Service — use at your own risk.
**Do I need cookies?**
For discovery, no — the official export already lists your likes. For
*downloading*, most platforms gate media behind login, so a Netscape
`cookies.txt` makes sync far more reliable. TikTok also often needs browser
impersonation (see `.env.example`).
**Does it run on Windows / Linux?**
Yes — it's Node + Docker + `yt-dlp`. Only the always-on service scripts
(`launchd`) are macOS-specific; on Linux run `npm run serve` under systemd.
Everything else is cross-platform.
**Why Postgres instead of SQLite?**
The **For you** ranker runs a single scoring SQL query per page over engagement
rollups; Postgres keeps that fast with a clean schema, and Docker Compose makes
it one command to start.
**Does it download photos too?**
By default it fetches videos only (`SYNC_REELS_ONLY=true`) and skips photo posts.
Set it to `false` to attempt everything.
**Can it auto-sync new likes?**
Not by default — discovery is export-based to stay scraping-free. An opt-in,
flagged Playwright auto-sync is on the roadmap.
---
## Legal & privacy
- Only use with **your own** exported data. The app does not bypass platform access controls.
- Media and exports live in `data/` (gitignored). Nothing personal belongs in git.
- Automated downloading may conflict with platform Terms of Service. Discovery uses
official exports; downloads are read-only fetches of content you already liked.
**Use at your own risk.**
---
## Roadmap
- [ ] Resume-from-last-position in the feed
- [ ] Auto-tagging and smart collections
- [ ] Opt-in, flagged Playwright auto-sync of new likes
- [ ] `gallery-dl` fallback engine for stubborn downloads
- [ ] One-click "reset library" in Admin
Have an idea? [Open an issue](https://github.com/ibrahimjspy/insta-like-player/issues)
or send a PR — see [CONTRIBUTING.md](CONTRIBUTING.md).
---
## Contributing
Issues and PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). For AI-assisted
development, see [CLAUDE.md](CLAUDE.md). Found a security issue? See
[SECURITY.md](SECURITY.md). Notable changes are tracked in
[CHANGELOG.md](CHANGELOG.md).
If this project saves you from losing liked videos to the algorithm, consider
**starring the repo** — it helps others find it.
## License
[MIT](LICENSE)