Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KickNoSub Web

Watch Kick subscriber-only VODs and cut clips out of them, straight from the browser.

Live: kicknosubviewer.duckdns.org

Paste a Kick VOD link, hit Play, and the video runs. Don't have a link? Type a channel name and browse its VODs from the grid. No account, no subscription, nothing to install. Found a moment worth keeping? Mark in, mark out, download the clip. The recording happens in your browser, so the file never leaves your machine and the server never stores it.

Features

  • Paste any Kick VOD URL (including sub-only) → instant playback via HLS
  • Or browse a channel: autocomplete on the channel name, then a paginated grid of its VODs
  • Mark In/Out points on the video timeline
  • Download the clipped segment as WebM, recorded client-side
  • Playback speed control
  • No login required, no subscription needed
  • Dark theme, responsive UI

How it works

  1. Reads video metadata from kick.com/api/v1/video/<uuid>, which returns usable JSON even behind a 403
  2. Uses cloudscraper to get past the Cloudflare protection on Kick's API
  3. Pulls the channel ARN and recording ID out of the thumbnail URLs returned by the v2 API
  4. Brute-forces the exact stream URL by testing ±10 minute offsets against 3 known CDN base URLs, since the path encodes the stream start time and the metadata timestamp does not match it exactly
  5. Plays the resulting HLS stream client-side via HLS.js
  6. Clips are captured in the browser with MediaRecorder, so nothing is transcoded or stored server-side

Step 4 is the fragile part. The CDN base URLs are hardcoded in BASE_URLS in server.py. If Kick moves to a different CDN prefix, or changes its thumbnail URL format, resolution stops working and the failure surfaces to the user as "stream not found" rather than as a server error. That is the first place to look when the site stops resolving VODs.

API

The frontend is served from the same Flask app and talks to three endpoints. All are rate-limited per IP by flask-limiter, using in-memory storage, so the counters reset whenever the process restarts.

Endpoint Limit Purpose
POST /api/resolve 10/min Body {"url": "<kick vod url>"} → resolved HLS URL and title
GET /api/channel?channel=<name> 15/min Channel profile: avatar, banner, followers, verified flag, current live state
GET /api/videos?channel=<name>&page=<n> 15/min One page of VODs: id, title, thumbnail, duration, date, viewers, plus hasMore

Channel names are validated against ^[a-zA-Z0-9_-]+$ and the page number is clamped to 1-50 before anything is forwarded to Kick.

Stack

  • Backend: Python/Flask + Gunicorn + cloudscraper, rate-limited with flask-limiter
  • Frontend: Vanilla HTML/JS + HLS.js
  • Clip engine: browser MediaRecorder (VP9/Opus when supported)
  • Process manager: PM2
  • Reverse proxy: Nginx

Deployment

Prerequisites

  • Python 3.8+
  • Node.js (for PM2)
  • Nginx (optional, for reverse proxy)

Setup

git clone https://github.com/Pkkls/kicknosub-web.git
cd kicknosub-web
pip install -r requirements.txt

Run locally

python server.py
# → http://localhost:3001

Production (PM2 + Nginx)

PM2 runs Gunicorn directly, with interpreter: 'none', so Node is only there as a process supervisor.

pm2 start ecosystem.config.js
pm2 save
# then point nginx at 127.0.0.1:3001

ecosystem.config.js hardcodes /home/ubuntu/kicknosub-web and the Gunicorn path under /home/ubuntu/.local/bin. Adjust both if you deploy anywhere else. Gunicorn runs 2 workers with a 120s timeout, since resolving a VOD can take several seconds of probing.

deploy.sh is stale: it still installs FFmpeg and runs npm install, neither of which this version needs. Use the steps above instead.

Usage

Play a VOD from its URL

  1. Copy a Kick VOD URL (e.g. https://kick.com/channel/videos/uuid)
  2. Paste it in the input field and click Play
  3. The video loads in the HLS player

Browse a channel

  1. Open the Browse tab
  2. Start typing a channel name, the autocomplete resolves it and shows the channel card with its live state
  3. Pick a VOD from the grid, Load more pages through the older ones
  4. Selecting a VOD sends it to the player

Clip a moment

  1. Use Mark In / Mark Out to set the clip boundaries
  2. Click Download Clip

The clip is recorded in real time by the browser: playback seeks to the In mark, runs through the range, and MediaRecorder captures the video element's stream as it goes. A three minute clip takes three minutes, or half that at 2x playback speed. Keep the tab in the foreground while it records, browsers throttle timers and rendering in background tabs and the capture suffers for it. Nothing is uploaded and the server never sees the file.

Credits

Disclaimer

For educational and research purposes only. Support creators by subscribing on Kick.

About

Watch Kick subscriber-only VODs and cut clips in the browser. No account, no install.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages