Skip to content

Conversation

@bastimeyer
Copy link
Member

The plugin is currently completely broken on master, because Kick has added a JS challenge for being able to access their REST APIs. The required token was previously simply set as a cookie from an initial HTTP request+response made on their front page which we could simply read. Now, a JS challenge similar to Twitch's has to be solved, where the cookie with the token is then set via JS APIs.

So in order to fix the plugin, Streamlink's webbrowser API has to be used where the JS challenge can be solved and the cookie value with the token be read. This works fine, even in headless mode.

I've added token caching, because apparently it's valid for 30 days (according to the cookie expiration times), but the cache expiration time is set to only a day for now, since there's no plugin argument for clearing the cache, and should it become invalid, users would need to remove the cached value manually.

It's probably better though to test the cached token on an API endpoint first and invalidate it if it's not working, and then request a new one. I'll have a look at this later before merging. Just wanted to open this PR now with the current changes.


$ streamlink -l debug kick.com/admiralbulldog best
[cli][debug] OS:         Linux-6.12.1-1-git-x86_64-with-glibc2.40
[cli][debug] Python:     3.13.0
[cli][debug] OpenSSL:    OpenSSL 3.4.0 22 Oct 2024
[cli][debug] Streamlink: 7.0.0+27.gf3c35469.dirty
[cli][debug] Dependencies:
[cli][debug]  certifi: 2024.8.30
[cli][debug]  isodate: 0.7.2
[cli][debug]  lxml: 5.3.0
[cli][debug]  pycountry: 24.6.1
[cli][debug]  pycryptodome: 3.21.0
[cli][debug]  PySocks: 1.7.1
[cli][debug]  requests: 2.32.3
[cli][debug]  trio: 0.27.0
[cli][debug]  trio-websocket: 0.11.1
[cli][debug]  urllib3: 2.2.3
[cli][debug]  websocket-client: 1.8.0
[cli][debug] Arguments:
[cli][debug]  url=kick.com/admiralbulldog
[cli][debug]  stream=['best']
[cli][debug]  --loglevel=debug
[cli][debug]  --player=/usr/bin/mpv
[cli][debug]  --webbrowser-headless=True
[cli][info] Found matching plugin kick for URL kick.com/admiralbulldog
[plugins.kick][info] Solving JS challenge using webbrowser API
[webbrowser.webbrowser][info] Launching web browser: /usr/bin/chromium (headless=True)
[webbrowser.webbrowser][debug] Waiting for web browser process to terminate
[utils.l10n][debug] Language code: en_US
[cli][info] Available streams: 160p (worst), 360p, 480p, 720p60, 1080p60 (best)
[cli][info] Opening stream: 1080p60 (hls)
[cli][info] Starting player: /usr/bin/mpv
$ ./script/test-plugin-urls.py kick -r LIVE_CHANNEL admiralbulldog -r VIDEO_ID 0fb687df-4012-4d16-b783-d8bf7b7f7705 -r CLIP_CHANNEL admiralbulldog -r CLIP_ID clip_01HSNHF69RPPR9JX0VQ6WM2YVC
:: https://kick.com/admiralbulldog
::  160p, 360p, 480p, 720p60, 1080p60, worst, best
:: https://kick.com/admiralbulldog?clip=clip_01HSNHF69RPPR9JX0VQ6WM2YVC
::  clip, worst, best
:: https://kick.com/video/0fb687df-4012-4d16-b783-d8bf7b7f7705
::  160p, 360p, 480p, 720p60, 1080p60, worst, best

@bastimeyer bastimeyer added the plugin issue A Plugin does not work correctly label Dec 5, 2024
@bastimeyer bastimeyer force-pushed the plugins/kick/js-challenge branch 2 times, most recently from 7f7abcc to b6efd2f Compare December 5, 2024 16:31
@bastimeyer bastimeyer force-pushed the plugins/kick/js-challenge branch from b6efd2f to 882347b Compare December 5, 2024 16:32
@bastimeyer
Copy link
Member Author

The token requirement seems to be disabled right now. No idea what's going on...
This will require further changes...

@bastimeyer bastimeyer marked this pull request as draft December 5, 2024 17:09
@bastimeyer bastimeyer closed this Dec 5, 2024
@bastimeyer bastimeyer deleted the plugins/kick/js-challenge branch December 5, 2024 17:46
@bastimeyer bastimeyer restored the plugins/kick/js-challenge branch December 5, 2024 17:52
@bastimeyer
Copy link
Member Author

I'm getting confused... I was just about to open a different PR with a simpler set of changes.

From what it looks like, arbitrary Authorization tokens work, but not always. For example, if the Authorization: Bearer None header is set, then in some cases the API returns a valid response, but sometimes it returns status 403. Same with any other random value, for example streamlink.utils.random.random_token().

That's why I thought that no token was required when I tested disabling the webbrowser API on this branch, because some streams were accessible.

@bastimeyer bastimeyer reopened this Dec 5, 2024
@bastimeyer
Copy link
Member Author

Now random tokens don't seem work anymore. This suggests that they are making active changes, or something else is going on. Doesn't make sense working on this right now...

@Hakkin
Copy link
Contributor

Hakkin commented Dec 14, 2024

FWIW, the kick plugin in master seems to work for me if I just add --http-header "Sec-Fetch-User=?1". Since you're seeing variable results, they might be doing A/B testing or something with the extra requirements.

@bastimeyer
Copy link
Member Author

Closed in favor of #6384

@streamlink streamlink locked and limited conversation to collaborators Jan 11, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

plugin issue A Plugin does not work correctly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants