[NOT WORKING FOR VODS] Downloading from fanclub sites for free

this is more of a documentation than a how-to, a bit of technical knowledge is required

UPDATE: the session id endpoint now returns 403 if you are not authenticated

“fanclub” sites are https://portal.nicochannel.jp and sites dedicated to one person, using the same website layout and infrastructure
here are a few of those sites as example

the api base url is https://nfc-api.<domain>/fc where <domain> is the domain of the site, so for example nicochannel.jp or canan8181.com

fanclub sites use hls to play streams and videos, the m3u8 playlist is obtained through the api
the url to the m3u8 is constructed like this


this format can be found at the /video_pages/<id> endpoint under data -> video_page -> video_stream -> authenticated_url

to get the session_id, make a POST request with an empty json object {} as body to the /video_pages/<id>/session_ids endpoint
as of right now (30th August 23) this endpoint requires the following header, this will likely change in the future

Content-Type: application/json
Fc_use_device: null
Origin: https://<domain>

no authentication is required for this endpoint, it works regardless of if you should have access to the content or not
this has been the case for over a year now and it seems to be either intentionally ignored by dwango or something is stopping them from implementing an authorization system

the returned json looks like this


now using the full url, you can access the m3u8 which is a master playlist containing all available quality options
the playlist for each quality contains the urls to the segments and an decryption key

unlike everything else, the decryption key is only accessible if you send a valid user agent
otherwise it will return the text Forbidden instead of the key, which downloaders like yt-dlp usually show as some kind of “key is not 16 bytes long” error

also note that a few months ago dwango has decided to completely block firefox, that means you can not use its user agent to access the key

finally, here are a couple examples of how you can get the session_id

curl -X POST --data {} -H "Content-Type: application/json" -H "Fc_use_device: null" -H "Origin: https://<domain>" https://nfc-api.<domain>/fc/video_pages/<id>/session_ids
import httpx

resp = httpx.post(f"https://nfc-api.<domain>/fc/video_pages/<id>/session_ids", json={},
		"Fc_use_device": "null",
		"Origin": <domain>

print("https://hls-auth.cloud.stream.co.jp/auth/index.m3u8?session_id=" + resp.json()["data"]["session_id"])