aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: 44c039b822726dfb9600f2f2f5eb7ac97dadd1a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# yt-local

[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
[![Python 3.7+](https://img.shields.io/badge/python-3.7+-blue.svg)](https://www.python.org/downloads/)
[![Tests](https://img.shields.io/badge/tests-passing-brightgreen.svg)](https://github.com/user234683/youtube-local)

A privacy-focused, browser-based YouTube client that routes requests through Tor for anonymous viewing—**without compromising on speed or features**.

[Features](#features) • [Install](#install) • [Usage](#usage) • [Screenshots](#screenshots)

---

> [!NOTE]
> How it works: yt-local mirrors YouTube's web requests (using the same Invidious/InnerTube endpoints as yt-dlp and Invidious) but strips JavaScript and serves a lightweight HTML frontend. No API keys needed.

## Overview

yt-local is a lightweight, self-hosted YouTube client written in Python that gives you:

- **Privacy-first**: All requests route through Tor by default (video optional), keeping you anonymous.
- **Fast page loads**: No lazy-loading, no layout reflows, instant comment rendering.
- **Full control**: Customize subtitles, related videos, comments, and playback speed.
- **High quality**: Supports all YouTube video qualities (144p–2160p) via DASH muxing.
- **Zero ads**: Clean interface, no tracking, no sponsored content.
- **Self-hosted**: You control the instance—no third-party trust required.

## Features

| Category      | Features                                                                               |
|---------------|----------------------------------------------------------------------------------------|
| Core          | Search, channels, playlists, watch pages, comments, subtitles (auto/manual)            |
| Privacy       | Optional Tor routing (including video), automatic circuit rotation on 429 errors       |
| Local         | Local playlists (durable against YouTube deletions), thumbnail caching                 |
| UI            | 3 themes (Light/Gray/Dark), theater mode, custom font selection                        |
| Config        | Fine-grained settings: subtitle mode, comment visibility, sponsorblock integration     |
| Performance   | No JavaScript required, instant page rendering, rate limiting with exponential backoff |
| Subscriptions | Import from YouTube Takeout (CSV/JSON), tag organization, mute channels                |

### Advanced Capabilities

- SponsorBlock integration — skip sponsored segments automatically
- Custom video speeds — 0.25x to 4x playback rate
- Video transcripts — accessible via transcript button
- Video quality muxing — combine separate video/audio streams for non-360p/720p resolutions
- Tor circuit rotation — automatic new identity on rate limiting (429)
- File downloading — download videos/audio (disabled by default, configurable)

## Screenshots

|                      Light Theme                      |                      Gray Theme                      |                      Dark Theme                      |
|:-----------------------------------------------------:|:----------------------------------------------------:|:----------------------------------------------------:|
| ![Light](https://pic.infini.fr/l7WINjzS/0Ru6MrhA.png) | ![Gray](https://pic.infini.fr/znnQXWNc/hL78CRzo.png) | ![Dark](https://pic.infini.fr/iXwFtTWv/mt2kS5bv.png) |

|                      Channel View                       |     Playlist View     |
|:-------------------------------------------------------:|:---------------------:|
| ![Channel](https://pic.infini.fr/JsenWVYe/SbdIQlS6.png) | *(similar structure)* |

---

## Install

### Windows

1. Download the latest [release ZIP](https://github.com/user234683/yt-local/releases)
2. Extract to any folder
3. Run `run.bat` to start

### GNU/Linux / macOS

```bash
# 1. Clone or extract the release
git clone https://github.com/user234683/yt-local.git
cd yt-local

# 2. Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate  # or `venv\Scripts\activate` on Windows

# 3. Install dependencies
pip install -r requirements.txt

# 4. Run the server
python3 server.py
```

> [!TIP]
> If `pip` isn't installed, use your distro's package manager (e.g., `sudo apt install python3-pip` on Debian/Ubuntu).

### Portable Mode

To keep settings and data in the same directory as the app:

```bash
# Create an empty settings.txt in the project root
touch settings.txt
python3 server.py
# Data now stored in ./data/ instead of ~/.yt-local/
```

---

## Usage

### Basic Access

1. Start the server:

```bash
python3 server.py
# Server runs on http://127.0.0.1:9010 (configurable in /settings)
```

2. Access YouTube via proxy:

```bash
http://localhost:9010/https://www.youtube.com/watch?v=vBgulDeV2RU
```

   All YouTube URLs must be prefixed with `http://localhost:9010/https://`.

3. (Optional) Use Redirector to auto-redirect YouTube URLs:

   - **Firefox**: [Redirector addon](https://addons.mozilla.org/firefox/addon/redirector/)
   - **Chrome**: [Redirector addon](https://chrome.google.com/webstore/detail/redirector/ocgpenflpmgnfapjedencafcfakcekcd)
   - **Pattern**: `^(https?://(?:[a-zA-Z0-9_-]*\.)?(?:youtube\.com|youtu\.be|youtube-nocookie\.com)/.*)`
   - **Redirect to**: `http://localhost:9010/$1`

> [!NOTE]
> To use embeds on web pages, make sure "Iframes" is checked under advanced options in your redirector rule.

### Tor Routing

> [!IMPORTANT]
> Recommended for privacy. In `/settings`, set **Route Tor** to `"On, except video"` (or `"On, including video"`), then save.

#### Running Tor

Option A: Tor Browser (easiest)

- Launch Tor Browser and leave it running
- yt-local uses port `9150` (Tor Browser default)

Option B: Standalone Tor

```bash
# Linux (Debian/Ubuntu)
sudo apt install tor
sudo systemctl enable --now tor

# Configure yt-local ports (if using default Tor ports):
# Tor port: 9150
# Tor control port: 9151
```

> [!WARNING]
> Video over Tor is bandwidth-intensive. Consider donating to [Tor node operators](https://torservers.net/donate.html) to sustain the network.

### Import Subscriptions

1. Go to [Google Takeout](https://takeout.google.com/takeout/custom/youtube)
2. Deselect all → select only **Subscriptions** → create export
3. Download and extract `subscriptions.csv` (path: `YouTube and YouTube Music/subscriptions/subscriptions.csv`)
4. In yt-local: **Subscriptions****Import** → upload CSV

> [!IMPORTANT]
> The CSV file must contain columns: `channel_id,channel_name,channel_url`

## Supported formats

- Google Takeout CSV
- Google Takeout JSON (legacy)
- NewPipe JSON export
- OPML (from YouTube's old subscription manager)

---

## Configuration

Visit `http://localhost:9010/settings` to configure:

| Setting            | Description                                     |
|--------------------|-------------------------------------------------|
| Route Tor          | Off / On (except video) / On (including video)  |
| Default subtitles  | Off / Manual only / Auto + Manual               |
| Comments mode      | Shown by default / Hidden by default / Never    |
| Related videos     | Same options as comments                        |
| Theme              | Light / Gray / Dark                             |
| Font               | Browser default / Serif / Sans-serif            |
| Default resolution | Auto / 144p–2160p                               |
| SponsorBlock       | Enable Sponsored segments skipping              |
| Proxy images       | Route thumbnails through yt-local (for privacy) |

---

## Troubleshooting

| Issue                        | Solution                                                                                     |
|------------------------------|----------------------------------------------------------------------------------------------|
| Port already in use          | Change `port_number` in `/settings` or kill existing process: `pkill -f "python3 server.py"` |
| 429 Too Many Requests        | Enable Tor routing for automatic IP rotation, or wait 5-10 minutes                           |
| Failed to connect to Tor     | Verify Tor is running: `tor --version` or launch Tor Browser                                 |
| Subscriptions not importing  | Ensure CSV has columns: `channel_id,channel_name,channel_url`                                |
| Settings persist across runs | Check `~/.yt-local/settings.txt` (non-portable) or `./settings.txt` (portable)               |

---

## Development

### Running Tests

```bash
source venv/bin/activate  # if not already in venv
make test
```

### Project Structure

```bash
yt-local/
├── youtube/              # Core application logic   ├── __init__.py      # Flask app entry point   ├── util.py          # HTTP utilities, Tor manager, fetch_url   ├── watch.py         # Video/playlist page handlers   ├── channel.py       # Channel page handlers   ├── playlist.py      # Playlist handlers   ├── search.py        # Search handlers   ├── comments.py      # Comment extraction/rendering   ├── subscriptions.py # Subscription management + SQLite   ├── local_playlist.py # Local playlist CRUD   ├── proto.py         # YouTube protobuf token generation   ├── yt_data_extract/ # Polymer JSON parsing abstractions   └── hls_cache.py     # HLS audio/video streaming proxy
├── templates/           # Jinja2 HTML templates
├── static/              # CSS/JS assets
├── translations/        # i18n files (Babel)
├── tests/               # pytest test suite
├── server.py            # WSGI entry point
├── settings.py          # Settings parser + admin page
├── generate_release.py  # Windows release builder
└── manage_translations.py # i18n maintenance script
```

> [!NOTE]
> For detailed architecture guidance, see [`docs/HACKING.md`](docs/HACKING.md).

### Contributing

Contributions welcome! Please:

1. Read [`docs/HACKING.md`](docs/HACKING.md) for coding guidelines
2. Follow [PEP 8](https://peps.python.org/pep-0008/) style (use `ruff format`)
3. Run tests before submitting: `pytest`
4. Ensure no security issues: `bandit -r .`
5. Update docs for new features

---

## Security Notes

- **No API keys required** — uses same endpoints as public YouTube web interface
- **Tor is optional** — disable in `/settings` if you prefer performance over anonymity
- **Rate limiting handled** — exponential backoff (max 5 retries) with automatic Tor circuit rotation
- **Path traversal protected** — user input validated against regex whitelists (CWE-22)
- **Subprocess calls secure** — build scripts use `subprocess.run([...])` instead of shell (CWE-78)

> [!NOTE]
> GPG key for release verification: `72CFB264DFC43F63E098F926E607CE7149F4D71C`

---

## Public Instances

yt-local is designed for self-hosting.

---

## Donate

This project is 100% free and open-source. If you'd like to support development:

- **Bitcoin**: `1JrC3iqs3PP5Ge1m1vu7WE8LEf4S85eo7y`
- **Tor node donation**: https://torservers.net/donate

---

## License

GNU Affero General Public License v3.0+

See [`LICENSE`](LICENSE) for full text.

### Exception for youtube-dl

Permission is granted to relicense code portions into youtube-dl's license (currently GPL) for direct inclusion into the [official youtube-dl repository](https://github.com/ytdl-org/youtube-dl). This exception **does not apply** to forks or other uses—those remain under AGPLv3.

---

## Similar Projects

| Project                                                      | Type     | Notes                                |
|--------------------------------------------------------------|----------|--------------------------------------|
| [invidious](https://github.com/iv-org/invidious)             | Server   | Multi-user instance, REST API        |
| [Yotter](https://github.com/ytorg/Yotter)                    | Server   | YouTube + Twitter integration        |
| [FreeTube](https://github.com/FreeTubeApp/FreeTube)          | Desktop  | Electron-based client                |
| [NewPipe](https://newpipe.schabi.org/)                       | Mobile   | Android-only, no JavaScript          |
| [mps-youtube](https://github.com/mps-youtube/mps-youtube)    | Terminal | CLI-based, text UI                   |
| [youtube-local](https://github.com/user234683/youtube-local) | Browser  | Original project (base for yt-local) |

---

Made for privacy-conscious users

Last updated: 2026-04-19